30#include <sys/socket.h>
38#include "../dpip/dpip.h"
46#define MSG(...) printf("[bookmarks dpi]: " __VA_ARGS__)
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" \
86static char *
Header =
"Content-type: text/html\n\n";
109"<title>Bookmarks</title>\n"
112"<body id='dillo_bm'>\n"
114" <h1>Bookmarks</h1>\n"
115" <div style='float: right; padding: 1em'>\n"
116" [<a href='dpi:/bm/modify'>Modify</a>]\n"
123"<title>Bookmarks</title>\n"
126"<body id='dillo_bm'>\n"
127" <h1>Bookmarks</h1>\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"
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"
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"
153#define modifypage_sections_header mainpage_sections_header
156" <li><a href='#s%d'>%s</a></li>\n";
162" <li><input type='checkbox' name='s%d'><a href='#s%d'>%s</a></li>\n";
168#define modifypage_sections_footer mainpage_sections_footer
175"<h2 id='s%d'>%s</h2>\n"
176"<ul class='main'>\n";
179"<h2 id='s%d'>%s</h2>\n"
180"<ul class='main'>\n";
184" <a href='%s'>%s</a>\n"
189" <input type='checkbox' name='url%d'>\n"
190" <a href='%s'>%s</a>\n"
196#define modifypage_section_card_footer mainpage_section_card_footer
212"<title>Bookmarks</title>\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"
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"
235"<title>Bookmarks</title>\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";
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"
256"<li style='padding: 0.5em'>\n"
257" <input type='text' name='s%d' size='64' value='%s'>\n"
264"<input type='submit' name='submit' value='Submit'>\n"
274"<title>Bookmarks</title>\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"
282" <input type='text' name='title' size='64'>\n"
285" <input type='text' name='url' size='64'>\n"
288" <input type='submit' name='submit' value='Submit'>\n"
289" or <a href='dpi:/bm/'>Cancel</a>\n"
306 for (i = 0, n = 0; str[i]; ++i)
310 new_str =
dNew(
char, strlen(str) + 6*n + 1);
313 for (i = 0, j = 0; str[i]; ++i) {
315 strcpy(new_str + j,
" ");
333 for (p = e = e_str; *e; e++, p++) {
336 }
else if (*e ==
'%') {
341 *p = (isdigit(e[1]) ? (e[1] -
'0') : (e[1] -
'A' + 10)) * 16 +
342 (isdigit(e[2]) ? (e[2] -
'0') : (e[2] -
'A' + 10));
372 return ((BmRec *)node)->key -
VOIDP2INT(key);
380 return ((BmRec *)node)->section -
VOIDP2INT(key);
388 return ((BmSec *)node)->section -
VOIDP2INT(key);
410static void Bms_add(
int section,
char *url,
char *title)
414 bm_node =
dNew(BmRec, 1);
416 bm_node->section = section;
429 sec_node =
dNew(BmSec, 1);
445 dFree(bm_node->title);
465 dFree(sec_node->title);
487 bm_node->section = target_section;
500 dFree(bm_node->title);
514 dFree(sec_node->title);
552 sec_node->o_sec = sec_node->section;
553 sec_node->section = i;
558 if (sec_node->section != sec_node->o_sec) {
561 if (bm_node->section == sec_node->o_sec)
562 bm_node->section = sec_node->section;
577 "echo \":s0: Unclassified\" > %s";
579 "grep -i \"href\" %s | "
580 "sed -e 's/<li><A HREF=\"/s0 /' -e 's/\">/ /' -e 's/<.*$//' >> %s";
585 if (access(
BmFile, F_OK) != 0) {
587 if (access(OldBmFile, F_OK) == 0) {
589 rc = system(dstr->
str);
591 MSG(
"Bookmarks: /bin/sh could not be executed\n");
592 }
else if (rc == -1) {
593 MSG(
"Bookmarks: process creation failure: %s\n",
597 rc = system(dstr->
str);
599 MSG(
"Bookmarks: /bin/sh could not be executed\n");
600 }
else if (rc == -1) {
601 MSG(
"Bookmarks: process creation failure: %s\n",
617 char *buf, *p, *url, *title, *u_title;
619 struct stat TimeStamp;
625 if (!(BmTxt = fopen(
BmFile,
"r"))) {
631 while ((buf =
dGetline(BmTxt)) != NULL) {
634 section = strtol(buf + 1, NULL, 10);
635 p = strchr(buf,
' ');
650 Bms_add(section, url, u_title);
653 }
else if (buf[0] ==
':' && buf[1] ==
's') {
655 p = strchr(buf + 2,
' ');
659 p = strchr(p,
'\n'); *p = 0;
671 MSG(
"Syntax error in bookmarks file:\n %s", buf);
691 struct stat TimeStamp;
693 if (stat(
BmFile, &TimeStamp) != 0) {
696 if (stat(
BmFile, &TimeStamp) != 0)
697 TimeStamp.st_mtime = 0;
725 if (stat(
BmFile, &BmStat) == 0 && BmStat.st_size > 256) {
727 rename(
BmFile, BmFileBak);
732 if (!(BmTxt = fopen(
BmFile,
"w"))) {
743 dStr_sprintf(dstr,
":s%d: %s\n", sec_node->section, u_title);
744 fwrite(dstr->
str, (
size_t)dstr->
len, 1, BmTxt);
751 if (bm_node->section == sec_node->section) {
754 bm_node->section, bm_node->url, u_title);
755 fwrite(dstr->
str, (
size_t)dstr->
len, 1, BmTxt);
779 char *msg=
"Added bookmark!";
784 Bms_add(section, url, u_title);
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;
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;
841 static Dstr *dstr = NULL;
865 sec_node->section, sec_node->section, sec_node->title);
882 sec_node->section, l_title);
889 if (bm_node->section == sec_node->section) {
891 bm_node->key, bm_node->url, bm_node->title);
942 static char *url1 = NULL;
943 static Dstr *dstr = NULL;
945 int i, key, n_sec, n_url;
973 p = strchr(url1,
'?');
974 for (q = p; (q = strstr(q,
"&s")); ++q) {
975 for (i = 0; isdigit(q[2+i]); ++i);
977 key = strtol(q + 2, NULL, 10);
980 sec_node->section, sec_node->title);
993 p = strchr(url1,
'?');
994 for (q = p; (q = strstr(q,
"&url")); ++q) {
995 for (i = 0; isdigit(q[4+i]); ++i);
997 key = strtol(q + 4, NULL, 10);
1000 bm_node->key, bm_node->title, bm_node->url);
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);
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);
1102 int n, section = 0, key;
1107 for (p = url; (p = strstr(p,
"&s")); ++p) {
1108 if (isdigit(p[2])) {
1109 section = strtol(p + 2, NULL, 10);
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);
1140 char *p, *q, *title;
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] ==
'=') {
1151 key = strtol(p + 1, NULL, 10);
1152 if ((q = strchr(p + 1,
'&')))
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] ==
'=') {
1170 key = strtol(p + 5, NULL, 10);
1171 if ((q = strchr(p + 5,
'&')))
1195 char *p, *title = NULL;
1200 if ((p = strstr(url,
"&title="))) {
1202 if ((p = strchr(title,
'&')))
1223 char *p, *q, *title, *u_title, *url;
1225 static int section = 0;
1231 for (q = s_url; (q = strstr(q,
"&s")); ++q) {
1232 for (i = 0; isdigit(q[2+i]); ++i);
1234 section = strtol(q + 2, NULL, 10);
1239 if (!(p = strstr(s_url,
"&title=")) ||
1240 !(q = strstr(s_url,
"&url=")))
1244 if ((p = strchr(title,
'&')))
1247 if ((p = strchr(url,
'&')))
1249 if (strlen(title) && strlen(url)) {
1253 Bms_add(section, url, u_title);
1282 p = strchr(url,
'?');
1283 if (strstr(p,
"operation=delete&")) {
1286 msg =
"Delete: you must mark what to delete!";
1288 }
else if (strstr(url,
"operation=move&")) {
1292 msg =
"Move: you must mark a target section!";
1294 msg =
"Move: can not move a section (yet).";
1296 msg =
"Move: you must mark some urls, and a target section!";
1298 }
else if (strstr(url,
"operation=modify&")) {
1301 msg =
"Modify: you must mark what to update!";
1303 }
else if (strstr(url,
"operation=modify2&")) {
1307 }
else if (strstr(url,
"operation=add_sec&")) {
1311 }
else if (strstr(url,
"operation=add_section&")) {
1315 }
else if (strstr(url,
"operation=add_url&")) {
1318 msg =
"Add url: only one target section is allowed!";
1320 }
else if (strstr(url,
"operation=add_url2&")) {
1324 }
else if (strstr(url,
"operation=none&")) {
1325 msg =
"No operation, just do nothing!";
1328 msg =
"Sorry, not implemented yet.";
1345 if (strstr(url,
"operation=delete&")) {
1351 }
else if (strstr(url,
"operation=move&")) {
1357 }
else if (strstr(url,
"operation=modify&")) {
1364 }
else if (strstr(url,
"operation=modify2&")) {
1370 }
else if (strstr(url,
"operation=add_sec&")) {
1376 }
else if (strstr(url,
"operation=add_section&")) {
1382 }
else if (strstr(url,
"operation=add_url&")) {
1390 }
else if (strstr(url,
"operation=add_url2&")) {
1407 static Dstr *dstr = NULL;
1430 sec_node->section, sec_node->title);
1447 sec_node->section, l_title);
1454 if (bm_node->section == sec_node->section) {
1456 bm_node->url, bm_node->title);
1484 static char *msg1=NULL, *msg2=NULL, *msg3=NULL;
1485 char *cmd, *d_cmd, *url, *title, *msg;
1497 MSG(
"ERROR: Unhandled DPIP_RAW mode!\n");
1501 BufSize = strlen(Buf);
1504 if (cmd && strcmp(cmd,
"chat") == 0) {
1511 }
else if (*msg ==
'I') {
1515 }
else if (*msg ==
'S') {
1527 if (cmd && strcmp(cmd,
"DpiBye") == 0) {
1528 MSG(
"(pid %d): Got DpiBye.\n", (
int)getpid());
1531 }
else if (cmd && strcmp(cmd,
"add_bookmark") == 0) {
1535 if (strlen(title) == 0) {
1537 title =
dStrdup(
"(Untitled)");
1545 }
else if (cmd && strcmp(cmd,
"open_url") == 0) {
1550 if (strcmp(url+4,
"/bm/modify") == 0) {
1554 }
else if (strncmp(url+4,
"/bm/modify?", 11) == 0) {
1579 "<HTML><body id='dillo_bm'> Error on the bookmarks server..."
1614 struct sockaddr_un spun;
1616 socklen_t address_size;
1625 signal (SIGINT, SIG_IGN);
1627 signal (SIGHUP, SIG_IGN);
1629 signal (SIGTERM, SIG_IGN);
1632 signal(SIGPIPE, SIG_IGN);
1639 address_size =
sizeof(
struct sockaddr_un);
1641 MSG(
"(v.13): accepting connections...\n");
1644 sock_fd = accept(STDIN_FILENO, (
struct sockaddr *)&spun, &address_size);
1645 if (sock_fd == -1) {
1656 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)
#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