1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-11-04 08:17:17 -05:00
elinks/src/bookmarks/backend/default.c
2022-01-31 15:32:24 +01:00

204 lines
4.6 KiB
C

/* Internal bookmarks support - default file format backend */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "elinks.h"
#include "bfu/dialog.h"
#include "bookmarks/bookmarks.h"
#include "bookmarks/backend/common.h"
#include "bookmarks/backend/default.h"
#include "util/file.h"
#include "util/memory.h"
#include "util/string.h"
#define BOOKMARKS_FILENAME "bookmarks"
/* Loads the bookmarks from file */
static void
read_bookmarks_default(FILE *f)
{
/* INBUF_SIZE = max. title length + 1 byte for separator
* + max. url length + 1 byte for separator + 5 bytes for depth
* + 1 byte for end of line + 1 byte for null char + reserve */
#define INBUF_SIZE ((MAX_STR_LEN - 1) + 1 + (MAX_STR_LEN - 1) + 1 + 5 + 1 + 1 \
+ MAX_STR_LEN)
char in_buffer[INBUF_SIZE]; /* read buffer */
struct bookmark *last_bm = NULL;
int last_depth = 0;
const int file_cp = get_cp_index("System");
/* TODO: Ignore lines with bad chars in title or url (?). -- Zas */
while (fgets(in_buffer, INBUF_SIZE, f)) {
char *title = in_buffer;
char *url;
char *depth_str;
int depth = 0;
char *flags = NULL;
char *line_end;
/* Load URL. */
url = strchr(in_buffer, '\t');
/* If separator is not found, or title is empty or too long,
* skip that line. */
if (!url || url == in_buffer
|| url - in_buffer > MAX_STR_LEN - 1)
continue;
*url = '\0';
url++;
/* Load depth. */
depth_str = strchr(url, '\t');
if (depth_str && depth_str - url > MAX_STR_LEN - 1)
continue;
if (depth_str) {
*depth_str = '\0';
depth_str++;
depth = atoi(depth_str);
int_bounds(&depth, 0, last_bm ? last_depth + 1 : 0);
/* Load flags. */
flags = strchr(depth_str, '\t');
if (flags) {
*flags = '\0';
flags++;
}
} else {
depth_str = url;
}
/* Load EOLN. */
line_end = strchr((flags ? flags : depth_str), '\n');
if (!line_end)
continue;
*line_end = '\0';
{
struct bookmark *root = NULL;
if (depth > 0) {
if (depth == last_depth) {
root = last_bm->root;
} else if (depth > last_depth) {
root = last_bm;
} else {
while (last_depth - depth) {
last_bm = last_bm->root;
last_depth--;
}
root = last_bm->root;
}
}
last_bm = add_bookmark_cp(root, 1, file_cp,
title, url);
last_depth = depth;
if (!*url && title[0] == '-' && title[1] == '\0') {
last_bm->box_item->type = BI_SEPARATOR;
} else {
while (flags && *flags && last_bm) {
switch (*flags) {
case 'F':
last_bm->box_item->type = BI_FOLDER;
break;
case 'E':
last_bm->box_item->expanded = 1;
break;
}
flags++;
}
}
}
}
#undef INBUF_SIZE
}
struct write_bookmarks_default
{
struct secure_save_info *ssi;
int save_folder_state;
int codepage;
struct conv_table *conv_table;
};
static void
write_bookmarks_default_inner(const struct write_bookmarks_default *out,
LIST_OF(struct bookmark) *bookmarks_list)
{
struct bookmark *bm;
foreach (bm, *bookmarks_list) {
char *title, *url;
title = convert_string(out->conv_table, bm->title,
strlen(bm->title), out->codepage,
CSM_NONE, NULL, NULL, NULL);
url = convert_string(out->conv_table, bm->url,
strlen(bm->url), out->codepage,
CSM_NONE, NULL, NULL, NULL);
secure_fprintf(out->ssi, "%s\t%s\t%d\t",
empty_string_or_(title), empty_string_or_(url),
bm->box_item->depth);
if (bm->box_item->type == BI_FOLDER) {
secure_fputc(out->ssi, 'F');
if (out->save_folder_state && bm->box_item->expanded)
secure_fputc(out->ssi, 'E');
}
secure_fputc(out->ssi, '\n');
if (!title || !url) {
secsave_errno = SS_ERR_OTHER;
out->ssi->err = ENOMEM;
}
mem_free_if(title);
mem_free_if(url);
if (out->ssi->err) break;
if (!list_empty(bm->child))
write_bookmarks_default_inner(out, &bm->child);
}
}
/* Saves the bookmarks to file */
static void
write_bookmarks_default(struct secure_save_info *ssi,
LIST_OF(struct bookmark) *bookmarks_list)
{
struct write_bookmarks_default out;
out.ssi = ssi;
out.save_folder_state = get_opt_bool("bookmarks.folder_state", NULL);
out.codepage = get_cp_index("System");
out.conv_table = get_translation_table(get_cp_index("UTF-8"),
out.codepage);
write_bookmarks_default_inner(&out, bookmarks_list);
}
static const char *
filename_bookmarks_default(int writing)
{
return BOOKMARKS_FILENAME;
}
struct bookmarks_backend default_bookmarks_backend = {
filename_bookmarks_default,
read_bookmarks_default,
write_bookmarks_default,
};