1 /* Internal bookmarks support - default file format backend */
2
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #include "elinks.h"
12
13 #include "bfu/dialog.h"
14 #include "bookmarks/bookmarks.h"
15 #include "bookmarks/backend/common.h"
16 #include "bookmarks/backend/default.h"
17 #include "util/file.h"
18 #include "util/memory.h"
19 #include "util/string.h"
20
21 #define BOOKMARKS_FILENAME "bookmarks"
22
23
24 /* Loads the bookmarks from file */
25 static void
read_bookmarks_default(FILE * f)26 read_bookmarks_default(FILE *f)
27 {
28 /* INBUF_SIZE = max. title length + 1 byte for separator
29 * + max. url length + 1 byte for separator + 5 bytes for depth
30 * + 1 byte for end of line + 1 byte for null char + reserve */
31 #define INBUF_SIZE ((MAX_STR_LEN - 1) + 1 + (MAX_STR_LEN - 1) + 1 + 5 + 1 + 1 \
32 + MAX_STR_LEN)
33 unsigned char in_buffer[INBUF_SIZE]; /* read buffer */
34 struct bookmark *last_bm = NULL;
35 int last_depth = 0;
36
37 /* TODO: Ignore lines with bad chars in title or url (?). -- Zas */
38 while (fgets(in_buffer, INBUF_SIZE, f)) {
39 unsigned char *title = in_buffer;
40 unsigned char *url;
41 unsigned char *depth_str;
42 int depth = 0;
43 unsigned char *flags = NULL;
44 unsigned char *line_end;
45
46 /* Load URL. */
47
48 url = strchr(in_buffer, '\t');
49
50 /* If separator is not found, or title is empty or too long,
51 * skip that line. */
52 if (!url || url == in_buffer
53 || url - in_buffer > MAX_STR_LEN - 1)
54 continue;
55 *url = '\0';
56 url++;
57
58 /* Load depth. */
59
60 depth_str = strchr(url, '\t');
61 if (depth_str && depth_str - url > MAX_STR_LEN - 1)
62 continue;
63
64 if (depth_str) {
65 *depth_str = '\0';
66 depth_str++;
67 depth = atoi(depth_str);
68 int_bounds(&depth, 0, last_bm ? last_depth + 1 : 0);
69
70 /* Load flags. */
71
72 flags = strchr(depth_str, '\t');
73 if (flags) {
74 *flags = '\0';
75 flags++;
76 }
77 } else {
78 depth_str = url;
79 }
80
81 /* Load EOLN. */
82
83 line_end = strchr(flags ? flags : depth_str, '\n');
84 if (!line_end)
85 continue;
86 *line_end = '\0';
87
88 {
89 struct bookmark *root = NULL;
90
91 if (depth > 0) {
92 if (depth == last_depth) {
93 root = last_bm->root;
94 } else if (depth > last_depth) {
95 root = last_bm;
96 } else {
97 while (last_depth - depth) {
98 last_bm = last_bm->root;
99 last_depth--;
100 }
101 root = last_bm->root;
102 }
103 }
104 last_bm = add_bookmark(root, 1, title, url);
105 last_depth = depth;
106
107 if (!*url && title[0] == '-' && title[1] == '\0') {
108 last_bm->box_item->type = BI_SEPARATOR;
109
110 } else {
111 while (flags && *flags && last_bm) {
112 switch (*flags) {
113 case 'F':
114 last_bm->box_item->type = BI_FOLDER;
115 break;
116 case 'E':
117 last_bm->box_item->expanded = 1;
118 break;
119 }
120 flags++;
121 }
122 }
123 }
124 }
125 #undef INBUF_SIZE
126 }
127
128 /* Saves the bookmarks to file */
129 static void
write_bookmarks_default(struct secure_save_info * ssi,struct list_head * bookmarks_list)130 write_bookmarks_default(struct secure_save_info *ssi,
131 struct list_head *bookmarks_list)
132 {
133 int folder_state = get_opt_bool("bookmarks.folder_state");
134 struct bookmark *bm;
135
136 foreach (bm, *bookmarks_list) {
137 secure_fprintf(ssi, "%s\t%s\t%d\t", bm->title, bm->url, bm->box_item->depth);
138 if (bm->box_item->type == BI_FOLDER) {
139 secure_fputc(ssi, 'F');
140 if (folder_state && bm->box_item->expanded)
141 secure_fputc(ssi, 'E');
142 }
143 secure_fputc(ssi, '\n');
144 if (ssi->err) break;
145
146 if (!list_empty(bm->child))
147 write_bookmarks_default(ssi, &bm->child);
148 }
149 }
150
151 static unsigned char *
filename_bookmarks_default(int writing)152 filename_bookmarks_default(int writing)
153 {
154 return BOOKMARKS_FILENAME;
155 }
156
157
158 struct bookmarks_backend default_bookmarks_backend = {
159 filename_bookmarks_default,
160 read_bookmarks_default,
161 write_bookmarks_default,
162 };
163