29#include <sys/socket.h>
37#include "../dpip/dpip.h"
45#define MSG(...) printf("[bookmarks dpi]: " __VA_ARGS__)
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" \
85static char *
Header =
"Content-type: text/html\n\n";
108"<title>Bookmarks</title>\n"
111"<body id='dillo_bm'>\n"
113" <h1>Bookmarks</h1>\n"
114" <div style='float: right; padding: 1em'>\n"
115" [<a href='dpi:/bm/modify'>Modify</a>]\n"
122"<title>Bookmarks</title>\n"
125"<body id='dillo_bm'>\n"
126" <h1>Bookmarks</h1>\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"
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"
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"
152#define modifypage_sections_header mainpage_sections_header
155" <li><a href='#s%d'>%s</a></li>\n";
161" <li><input type='checkbox' name='s%d'><a href='#s%d'>%s</a></li>\n";
167#define modifypage_sections_footer mainpage_sections_footer
174"<h2 id='s%d'>%s</h2>\n"
175"<ul class='main'>\n";
178"<h2 id='s%d'>%s</h2>\n"
179"<ul class='main'>\n";
183" <a href='%s'>%s</a>\n"
188" <input type='checkbox' name='url%d'>\n"
189" <a href='%s'>%s</a>\n"
195#define modifypage_section_card_footer mainpage_section_card_footer
211"<title>Bookmarks</title>\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"
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"
234"<title>Bookmarks</title>\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";
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"
255"<li style='padding: 0.5em'>\n"
256" <input type='text' name='s%d' size='64' value='%s'>\n"
263"<input type='submit' name='submit' value='Submit'>\n"
273"<title>Bookmarks</title>\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"
281" <input type='text' name='title' size='64'>\n"
284" <input type='text' name='url' size='64'>\n"
287" <input type='submit' name='submit' value='Submit'>\n"
288" or <a href='dpi:/bm/'>Cancel</a>\n"
305 for (i = 0, n = 0; str[i]; ++i)
309 new_str =
dNew(
char, strlen(str) + 6*n + 1);
312 for (i = 0, j = 0; str[i]; ++i) {
314 strcpy(new_str + j,
" ");
332 for (p = e = e_str; *e; e++, p++) {
335 }
else if (*e ==
'%') {
340 *p = (
dIsdigit(e[1]) ? (e[1] -
'0') : (e[1] -
'A' + 10)) * 16 +
341 (
dIsdigit(e[2]) ? (e[2] -
'0') : (e[2] -
'A' + 10));
371 return ((BmRec *)node)->key -
VOIDP2INT(key);
379 return ((BmRec *)node)->section -
VOIDP2INT(key);
387 return ((BmSec *)node)->section -
VOIDP2INT(key);
409static void Bms_add(
int section,
char *url,
char *title)
413 bm_node =
dNew(BmRec, 1);
415 bm_node->section = section;
428 sec_node =
dNew(BmSec, 1);
444 dFree(bm_node->title);
464 dFree(sec_node->title);
486 bm_node->section = target_section;
499 dFree(bm_node->title);
513 dFree(sec_node->title);
551 sec_node->o_sec = sec_node->section;
552 sec_node->section = i;
557 if (sec_node->section != sec_node->o_sec) {
560 if (bm_node->section == sec_node->o_sec)
561 bm_node->section = sec_node->section;
576 "echo \":s0: Unclassified\" > %s";
578 "grep -i \"href\" %s | "
579 "sed -e 's/<li><A HREF=\"/s0 /' -e 's/\">/ /' -e 's/<.*$//' >> %s";
584 if (access(
BmFile, F_OK) != 0) {
586 if (access(OldBmFile, F_OK) == 0) {
588 rc = system(dstr->
str);
590 MSG(
"Bookmarks: /bin/sh could not be executed\n");
591 }
else if (rc == -1) {
592 MSG(
"Bookmarks: process creation failure: %s\n",
596 rc = system(dstr->
str);
598 MSG(
"Bookmarks: /bin/sh could not be executed\n");
599 }
else if (rc == -1) {
600 MSG(
"Bookmarks: process creation failure: %s\n",
616 char *buf, *p, *url, *title, *u_title;
618 struct stat TimeStamp;
624 if (!(BmTxt = fopen(
BmFile,
"r"))) {
630 while ((buf =
dGetline(BmTxt)) != NULL) {
633 section = strtol(buf + 1, NULL, 10);
634 p = strchr(buf,
' ');
649 Bms_add(section, url, u_title);
652 }
else if (buf[0] ==
':' && buf[1] ==
's') {
654 p = strchr(buf + 2,
' ');
658 p = strchr(p,
'\n'); *p = 0;
670 MSG(
"Syntax error in bookmarks file:\n %s", buf);
690 struct stat TimeStamp;
692 if (stat(
BmFile, &TimeStamp) != 0) {
695 if (stat(
BmFile, &TimeStamp) != 0)
696 TimeStamp.st_mtime = 0;
724 if (stat(
BmFile, &BmStat) == 0 && BmStat.st_size > 256) {
726 rename(
BmFile, BmFileBak);
731 if (!(BmTxt = fopen(
BmFile,
"w"))) {
742 dStr_sprintf(dstr,
":s%d: %s\n", sec_node->section, u_title);
743 fwrite(dstr->
str, (
size_t)dstr->
len, 1, BmTxt);
750 if (bm_node->section == sec_node->section) {
753 bm_node->section, bm_node->url, u_title);
754 fwrite(dstr->
str, (
size_t)dstr->
len, 1, BmTxt);
778 char *msg=
"Added bookmark!";
783 Bms_add(section, url, u_title);
807 if ((p = strchr(url,
'?'))) {
808 for (q = p; (q = strstr(q,
"&url")); ++q) {
810 *n_url += (q[4+i] ==
'=') ? 1 : 0;
812 for (q = p; (q = strstr(q,
"&s")); ++q) {
814 *n_sec += (q[2+i] ==
'=') ? 1 : 0;
840 static Dstr *dstr = NULL;
864 sec_node->section, sec_node->section, sec_node->title);
881 sec_node->section, l_title);
888 if (bm_node->section == sec_node->section) {
890 bm_node->key, bm_node->url, bm_node->title);
941 static char *url1 = NULL;
942 static Dstr *dstr = NULL;
944 int i, key, n_sec, n_url;
972 p = strchr(url1,
'?');
973 for (q = p; (q = strstr(q,
"&s")); ++q) {
976 key = strtol(q + 2, NULL, 10);
979 sec_node->section, sec_node->title);
992 p = strchr(url1,
'?');
993 for (q = p; (q = strstr(q,
"&url")); ++q) {
996 key = strtol(q + 4, NULL, 10);
999 bm_node->key, bm_node->title, bm_node->url);
1060 p = strchr(url,
'?');
1061 for (ns = 0; (p = strstr(p,
"&s")); ++p) {
1063 key = strtol(p + 2, NULL, 10);
1070 p = strchr(url,
'?');
1071 for (nb = 0; (p = strstr(p,
"&url")); ++p) {
1073 key = strtol(p + 4, NULL, 10);
1101 int n, section = 0, key;
1106 for (p = url; (p = strstr(p,
"&s")); ++p) {
1108 section = strtol(p + 2, NULL, 10);
1116 p = strchr(url,
'?');
1117 for (n = 0; (p = strstr(p,
"&url")); ++p) {
1119 key = strtol(p + 4, NULL, 10);
1139 char *p, *q, *title;
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] ==
'=') {
1150 key = strtol(p + 1, NULL, 10);
1151 if ((q = strchr(p + 1,
'&')))
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] ==
'=') {
1169 key = strtol(p + 5, NULL, 10);
1170 if ((q = strchr(p + 5,
'&')))
1194 char *p, *title = NULL;
1199 if ((p = strstr(url,
"&title="))) {
1201 if ((p = strchr(title,
'&')))
1222 char *p, *q, *title, *u_title, *url;
1224 static int section = 0;
1230 for (q = s_url; (q = strstr(q,
"&s")); ++q) {
1231 for (i = 0;
dIsdigit(q[2+i]); ++i);
1233 section = strtol(q + 2, NULL, 10);
1238 if (!(p = strstr(s_url,
"&title=")) ||
1239 !(q = strstr(s_url,
"&url=")))
1243 if ((p = strchr(title,
'&')))
1246 if ((p = strchr(url,
'&')))
1248 if (strlen(title) && strlen(url)) {
1252 Bms_add(section, url, u_title);
1281 p = strchr(url,
'?');
1282 if (strstr(p,
"operation=delete&")) {
1285 msg =
"Delete: you must mark what to delete!";
1287 }
else if (strstr(url,
"operation=move&")) {
1291 msg =
"Move: you must mark a target section!";
1293 msg =
"Move: can not move a section (yet).";
1295 msg =
"Move: you must mark some urls, and a target section!";
1297 }
else if (strstr(url,
"operation=modify&")) {
1300 msg =
"Modify: you must mark what to update!";
1302 }
else if (strstr(url,
"operation=modify2&")) {
1306 }
else if (strstr(url,
"operation=add_sec&")) {
1310 }
else if (strstr(url,
"operation=add_section&")) {
1314 }
else if (strstr(url,
"operation=add_url&")) {
1317 msg =
"Add url: only one target section is allowed!";
1319 }
else if (strstr(url,
"operation=add_url2&")) {
1323 }
else if (strstr(url,
"operation=none&")) {
1324 msg =
"No operation, just do nothing!";
1327 msg =
"Sorry, not implemented yet.";
1344 if (strstr(url,
"operation=delete&")) {
1350 }
else if (strstr(url,
"operation=move&")) {
1356 }
else if (strstr(url,
"operation=modify&")) {
1363 }
else if (strstr(url,
"operation=modify2&")) {
1369 }
else if (strstr(url,
"operation=add_sec&")) {
1375 }
else if (strstr(url,
"operation=add_section&")) {
1381 }
else if (strstr(url,
"operation=add_url&")) {
1389 }
else if (strstr(url,
"operation=add_url2&")) {
1406 static Dstr *dstr = NULL;
1429 sec_node->section, sec_node->title);
1446 sec_node->section, l_title);
1453 if (bm_node->section == sec_node->section) {
1455 bm_node->url, bm_node->title);
1483 static char *msg1=NULL, *msg2=NULL, *msg3=NULL;
1484 char *cmd, *d_cmd, *url, *title, *msg;
1496 MSG(
"ERROR: Unhandled DPIP_RAW mode!\n");
1500 BufSize = strlen(Buf);
1503 if (cmd && strcmp(cmd,
"chat") == 0) {
1510 }
else if (*msg ==
'I') {
1514 }
else if (*msg ==
'S') {
1526 if (cmd && strcmp(cmd,
"DpiBye") == 0) {
1527 MSG(
"(pid %d): Got DpiBye.\n", (
int)getpid());
1530 }
else if (cmd && strcmp(cmd,
"add_bookmark") == 0) {
1534 if (strlen(title) == 0) {
1536 title =
dStrdup(
"(Untitled)");
1544 }
else if (cmd && strcmp(cmd,
"open_url") == 0) {
1549 if (strcmp(url+4,
"/bm/modify") == 0) {
1553 }
else if (strncmp(url+4,
"/bm/modify?", 11) == 0) {
1578 "<HTML><body id='dillo_bm'> Error on the bookmarks server..."
1613 struct sockaddr_un spun;
1615 socklen_t address_size;
1624 signal (SIGINT, SIG_IGN);
1626 signal (SIGHUP, SIG_IGN);
1628 signal (SIGTERM, SIG_IGN);
1631 signal(SIGPIPE, SIG_IGN);
1638 address_size =
sizeof(
struct sockaddr_un);
1640 MSG(
"(v.13): accepting connections...\n");
1643 sock_fd = accept(STDIN_FILENO, (
struct sockaddr *)&spun, &address_size);
1644 if (sock_fd == -1) {
1655 MSG(
"can't authenticate request: %s\n",
dStrerror(errno));
static int Bmsrv_send_reload_request(Dsh *sh, char *url)
static int Bms_sec_by_number_cmp(const void *node, const void *key)
static int Bmsrv_parse_token(Dsh *sh, char *Buf)
static void Bms_add(int section, char *url, char *title)
static const char * modifypage_section_card_header
static int Bmsrv_send_modify_update(Dsh *sh, char *url)
static const char * mainpage_sections_header
static int Bmsrv_send_modify_page_add_section(Dsh *sh)
static const char * modifypage_update_footer
static int Bms_save(void)
#define modifypage_sections_footer
static const char * modifypage_middle1
static int Bmsrv_modify_delete(char *url)
static const char * modifypage_footer
static int Bmsrv_send_modify_page(Dsh *sh)
static const char * mainpage_section_card_footer
static const char * modifypage_add_url
static int MODIFY_PAGE_NUM
static const char * modifypage_update_item
static int Bmsrv_check_modify_request(Dsh *sh, char *url)
static const char * mainpage_footer
static void Bms_check_import(void)
static const char * modifypage_sections_item
static BmSec * Bms_get_sec(int key)
static time_t BmFileTimeStamp
static void Bms_move(int key, int target_section)
static void cleanup(void)
static const char * modifypage_update_item_header
static void Bms_free(void)
static void Bmsrv_count_urls_and_sections(char *url, int *n_sec, int *n_url)
static int send_bm_page(Dsh *sh)
static void Bms_update_title(int key, char *n_title)
static int Bmsrv_add_bm(Dsh *sh, char *url, char *title)
static const char * mainpage_sections_footer
static int Bmsrv_modify_update(char *url)
static int Bmsrv_modify_move(char *url)
static void Bms_sec_add(char *title)
static const char * mainpage_header
static int Bmsrv_dpi_send_status_msg(Dsh *sh, char *str)
#define modifypage_sections_header
static const char * modifypage_update_item2
static int Bms_load(void)
static const char * modifypage_update_header
static void termination_handler(int signum)
static const char * mainpage_section_card_header
static const char * mainpage_section_card_item
static void Unencode_str(char *e_str)
static int Bms_node_by_key_cmp(const void *node, const void *key)
static int Bmsrv_modify_add_url(Dsh *sh, char *s_url)
static void Bms_sec_del(int section)
static const char * modifypage_update_title
static const char * sections_sep
static void Bms_update_sec_title(int key, char *n_title)
static int Bmsrv_send_modify_answer(Dsh *sh, char *url)
static BmRec * Bms_get(int key)
static const char * modifypage_section_card_item
static int Bmsrv_modify_add_section(char *url)
static const char * modifypage_update_item_footer
static const char * mainpage_middle1
static const char * modifypage_add_section_page
static const char * modifypage_header
#define modifypage_section_card_footer
static int Bmsrv_process_modify_request(Dsh *sh, char *url)
static void Bms_normalize(void)
static char * make_one_line_str(char *str)
static int Bmsrv_send_modify_page_add_url(Dsh *sh)
static const char * mainpage_sections_item
static int Bms_cond_load(void)
static void Bms_del(int key)
static int Bms_node_by_section_cmp(const void *node, const void *key)
char * dGetline(FILE *stream)
Get a line from a FILE stream.
char * dStrconcat(const char *s1,...)
Concatenate a NULL-terminated list of strings.
char * dStrdup(const char *s)
Dlist * dList_new(int size)
Create a new empty list.
int dStrnAsciiCasecmp(const char *s1, const char *s2, size_t n)
int dList_length(Dlist *lp)
For completing the ADT.
void * dList_nth_data(Dlist *lp, int n0)
Return the nth data item, NULL when not found or 'n0' is out of range.
void dStr_free(Dstr *ds, int all)
Free a dillo string.
char * dStrndup(const char *s, size_t sz)
void dStr_sprintf(Dstr *ds, const char *format,...)
Printf-like function.
Dstr * dStr_new(const char *s)
Create a new string.
void dList_append(Dlist *lp, void *data)
Append a data item to the list.
void * dList_find_custom(Dlist *lp, const void *data, dCompareFunc func)
Search a data item using a custom function.
void dList_remove(Dlist *lp, const void *data)
char * dGethomedir(void)
Return the home directory in a static string (don't free)
static int dIsdigit(unsigned char c)
#define dNew(type, count)
static void error(char *msg)
void a_Dpip_dsh_free(Dsh *dsh)
Free the SockHandler structure.
char * a_Dpip_build_cmd(const char *format,...)
Printf like function for building dpip commands.
int a_Dpip_dsh_write_str(Dsh *dsh, int flush, const char *str)
Convenience function.
char * a_Dpip_dsh_read_token(Dsh *dsh, int blocking)
Return a newlly allocated string with the next dpip token in the socket.
void a_Dpip_dsh_close(Dsh *dsh)
Close this socket for reading and writing.
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...
int a_Dpip_check_auth(const char *auth_tag)
Check whether the given 'auth' string equals what dpid saved.
Dsh * a_Dpip_dsh_new(int fd_in, int fd_out, int flush_sz)
Create and initialize a dpip socket handler.
#define DPIP_RAW
Raw data in the socket
char * Escape_html_str(const char *str)
char * Unescape_html_str(const char *str)
char * Escape_uri_str(const char *str, const char *p_esc_set)
Dpip socket handler type.
int mode
mode flags: DPIP_TAG | DPIP_LAST_TAG | DPIP_RAW