⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xbel.c

📁 elinks下lynx是最重要的二个文本浏览器, 在linux下非常实用, elinks也是gentoo安装过程中默认使用的浏览器, 这是elinks源代码
💻 C
字号:
/* Internal bookmarks XBEL bookmarks basic support *//* * TODO: Decent XML output. * TODO: Validation of the document (with librxp?). An invalid document can *       crash elinks. * TODO: Support all the XBEL elements. */#ifdef HAVE_CONFIG_H#include "config.h"#endif /* HAVE_CONFIG_H */#include <ctype.h>#include <expat.h>#include <stdio.h>#include <stdlib.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include "elinks.h"#include "bfu/dialog.h"#include "bookmarks/bookmarks.h"#include "bookmarks/backend/common.h"#include "bookmarks/backend/xbel.h"#include "intl/charsets.h"#include "intl/gettext/libintl.h"#include "util/conv.h"#include "util/lists.h"#include "util/string.h"#define BOOKMARKS_XBEL_FILENAME		"bookmarks.xbel"/* Elements' attributes */struct attributes {	LIST_HEAD(struct attributes);	unsigned char *name;};/* Prototypes */static void on_element_open(void *data, const char *name, const char **attr);static void on_element_close(void *data, const char *name);static void on_text(void *data, const XML_Char *text, int len);static struct tree_node *new_node(struct tree_node *parent);static void free_node(struct tree_node *node);static void free_xbeltree(struct tree_node *node);static struct tree_node *get_child(struct tree_node *node, unsigned char *name);static unsigned char *get_attribute_value(struct attributes *attr,					  unsigned char *name);static void read_bookmarks_xbel(FILE *f);static unsigned char * filename_bookmarks_xbel(int writing);static int xbeltree_to_bookmarks_list(struct tree_node *root,				      struct bookmark *current_parent);static void write_bookmarks_list(struct secure_save_info *ssi,				 struct list_head *bookmarks_list,				 int n, int folder_state);static void write_bookmarks_xbel(struct secure_save_info *ssi,				 struct list_head *bookmarks_list);/* Element */struct tree_node {	unsigned char *name;		/* Name of the element */	unsigned char *text;		/* Text inside the element */	struct attributes *attrs;	/* Attributes of the element */	struct tree_node *parent;	struct tree_node *children;	struct tree_node *prev;	struct tree_node *next;};static struct tree_node *root_node = NULL;static struct tree_node *current_node = NULL;/* This is 1 so that we won't fail miserably if we read bookmarks in a * different format. */static int readok = 1;static voidread_bookmarks_xbel(FILE *f){	unsigned char in_buffer[BUFSIZ];	XML_Parser p;	int done = 0;	int err = 0;	readok = 0;	p = XML_ParserCreate(NULL);	if (!p) {		ERROR(gettext("read_bookmarks_xbel(): Error in XML_ParserCreate()"));		return;	}	XML_SetElementHandler(p, on_element_open, on_element_close);	XML_SetCharacterDataHandler(p, on_text);	while (!done && !err) {		size_t len = fread(in_buffer, 1, BUFSIZ, f);		if (ferror(f)) {			ERROR(gettext("read_bookmarks_xbel(): Error reading %s"),			      filename_bookmarks_xbel(0));			err = 1;		} else {			done = feof(f);			if (!err && !XML_Parse(p, in_buffer, len, done)) {				usrerror(gettext("Parse error while processing "				         "XBEL bookmarks in %s at line %d "					 "column %d:\n%s"),				      filename_bookmarks_xbel(0),				      XML_GetCurrentLineNumber(p),				      XML_GetCurrentColumnNumber(p),				      XML_ErrorString(XML_GetErrorCode(p)));				err = 1;			}		}	}	if (!err) readok = xbeltree_to_bookmarks_list(root_node->children, NULL); /* Top node is xbel */	XML_ParserFree(p);	free_xbeltree(root_node);}static voidwrite_bookmarks_xbel(struct secure_save_info *ssi,		     struct list_head *bookmarks_list){	int folder_state = get_opt_bool("bookmarks.folder_state");	/* We check for readok in filename_bookmarks_xbel(). */	secure_fputs(ssi,		"<?xml version=\"1.0\"?>\n"		"<!DOCTYPE xbel PUBLIC \"+//IDN python.org//DTD XML "		"Bookmark Exchange Language 1.0//EN//XML\"\n"		"		       "		"\"http://www.python.org/topics/xml/dtds/xbel-1.0.dtd\">\n\n"		"<xbel>\n\n\n");	write_bookmarks_list(ssi, bookmarks_list, 0, folder_state);	secure_fputs(ssi, "\n</xbel>\n");}static unsigned char *filename_bookmarks_xbel(int writing){	if (writing && !readok) return NULL;	return BOOKMARKS_XBEL_FILENAME;}static voidindentation(struct secure_save_info *ssi, int num){	int i;	for (i = 0; i < num; i++)		secure_fputs(ssi, "    ");}/* FIXME This is totally broken, we should use the Unicode value in *       numeric entities. *       Additionally it is slow, not elegant, incomplete and *       if you pay enough attention you can smell the unmistakable *       odor of doom coming from it. --fabio */static voidprint_xml_entities(struct secure_save_info *ssi, const unsigned char *str){#define accept_char(x) (isident((x)) || (x) == ' ' || (x) == '.' \				 || (x) == ':' || (x) == ';' \				 || (x) == '/' || (x) == '(' \				 || (x) == ')' || (x) == '}' \				 || (x) == '{' || (x) == '%' \				 || (x) == '+')	static int cp = 0;	if (!cp) get_cp_index("us-ascii");	for (; *str; str++) {		if (accept_char(*str))			secure_fputc(ssi, *str);		else {			if (isascii(*str)) {				secure_fprintf(ssi, "&#%i;", (int) *str);			}			else {				unsigned char *s = u2cp_no_nbsp(*str, cp);				if (s) print_xml_entities(ssi, s);			}		}	}#undef accept_char}static voidwrite_bookmarks_list(struct secure_save_info *ssi,		     struct list_head *bookmarks_list,		     int n, int folder_state){	struct bookmark *bm;	foreach (bm, *bookmarks_list) {		indentation(ssi, n + 1);		if (bm->box_item->type == BI_FOLDER) {			int expanded = folder_state && bm->box_item->expanded;			secure_fputs(ssi, "<folder folded=\"");			secure_fputs(ssi, expanded ? "no" : "yes");			secure_fputs(ssi, "\">\n");			indentation(ssi, n + 2);			secure_fputs(ssi, "<title>");			print_xml_entities(ssi, bm->title);			secure_fputs(ssi, "</title>\n");			if (!list_empty(bm->child))				write_bookmarks_list(ssi, &bm->child, n + 2, folder_state);			indentation(ssi, n + 1);			secure_fputs(ssi, "</folder>\n\n");		} else if (bm->box_item->type == BI_LEAF) {			secure_fputs(ssi, "<bookmark href=\"");			print_xml_entities(ssi, bm->url);			secure_fputs(ssi, "\">\n");			indentation(ssi, n + 2);			secure_fputs(ssi, "<title>");			print_xml_entities(ssi, bm->title);			secure_fputs(ssi, "</title>\n");			indentation(ssi, n + 1);			secure_fputs(ssi, "</bookmark>\n\n");		} else if (bm->box_item->type == BI_SEPARATOR) {			secure_fputs(ssi, "<separator/>\n\n");		}	}}static voidon_element_open(void *data, const char *name, const char **attr){	struct attributes *attribute;	struct tree_node *node;	node = new_node(current_node);	if (!node) return;	if (root_node) {		if (current_node->children) {			struct tree_node *tmp;			tmp = current_node->children;			current_node->children = node;			current_node->children->next = tmp;			current_node->children->prev = NULL;		}		else current_node->children = node;	}	else root_node = node;	current_node = node;	current_node->name = stracpy((unsigned char *) name);	if (!current_node->name) {		mem_free(current_node);		return;	}	while (*attr) {		unsigned char *tmp = stracpy((unsigned char *) *attr);		if (!tmp) {			free_node(current_node);			return;		}		attribute = mem_calloc(1, sizeof(*attribute));		if (!attribute) {			mem_free(tmp);			free_node(current_node);			return;		}		attribute->name = tmp;		add_to_list(*current_node->attrs, attribute);		++attr;	}}static voidon_element_close(void *data, const char *name){	current_node = current_node->parent;}static unsigned char *delete_whites(unsigned char *s){	unsigned char *r;	int count = 0, c = 0, i;	int len = strlen(s);	r = mem_alloc(len + 1);	if (!r) return NULL;	for (i = 0; i < len; i++) {		if (isspace(s[i])) {			if (count == 1) continue;			else count = 1;		}		else count = 0;		if (s[i] == '\n' || s[i] == '\t')			r[c++] = ' ';		else r[c++] = s[i];	}	r[c] = '\0';	/* XXX This should never return NULL, right? wrong! --fabio */	/* r = mem_realloc(r, strlen(r + 1)); */	return r;}static voidon_text(void *data, const XML_Char *text, int len){	char *tmp;	int len2 = 0;	if (len) {		len2 = current_node->text ? strlen(current_node->text) : 0;		tmp = mem_realloc(current_node->text, (size_t) (len + 1 + len2));		/* Out of memory */		if (!tmp) return;		strncpy(tmp + len2, text, len);		tmp[len + len2] = '\0';		current_node->text = delete_whites(tmp);		mem_free(tmp);	}}/* xbel_tree_to_bookmarks_list: returns 0 on fail, *				      1 on success */static intxbeltree_to_bookmarks_list(struct tree_node *node,			   struct bookmark *current_parent){	struct bookmark *tmp;	struct tree_node *title;	static struct bookmark *lastbm;	while (node) {		if (!strcmp(node->name, "bookmark")) {			unsigned char *href;			title = get_child(node, "title");			href = get_attribute_value(node->attrs, "href");			tmp = add_bookmark(current_parent, 0,					   /* The <title> element is optional */					   title ? title->text						 : (unsigned char *) gettext("No title"),					   /* XXX: The href attribute isn't optional but					    * we don't validate the source XML yet, so					    * we can't always assume a non NULL value for					    * get_attribute_value() */					   href ? href						: (unsigned char *) gettext("No URL"));			/* Out of memory */			if (!tmp) return 0;			tmp->root = current_parent;			lastbm = tmp;		} else if (!strcmp(node->name, "folder")) {			unsigned char *folded;			title = get_child(node, "title");			tmp = add_bookmark(current_parent, 0,					   title ? title->text						 : (unsigned char *) gettext("No title"),					   NULL);			/* Out of memory */			if (!tmp) return 0;			folded = get_attribute_value(node->attrs, "folded");			if (folded && !strcmp(folded, "no"))				tmp->box_item->expanded = 1;			lastbm = tmp;		} else if (!strcmp(node->name, "separator")) {			tmp = add_bookmark(current_parent, 0, "-", "");			/* Out of memory */			if (!tmp) return 0;			tmp->root = current_parent;			lastbm = tmp;		}		if (node->children) {			int ret;			/* If this node is a <folder> element, current parent			 * changes */			ret = (!strcmp(node->name, "folder") ?				xbeltree_to_bookmarks_list(node->children,							   lastbm) :				xbeltree_to_bookmarks_list(node->children,							   current_parent));			/* Out of memory */			if (!ret) return 0;		}		node = node->next;	}	/* Success */	return 1;}static voidfree_xbeltree(struct tree_node *node){	struct tree_node *next_node;	while (node) {		if (node->children)			free_xbeltree(node->children);		next_node = node->next;		free_node(node);		node = next_node;	}}static struct tree_node *get_child(struct tree_node *node, unsigned char *name){	struct tree_node *ret;	if (!node) return NULL;	ret = node->children;	while (ret) {		if (!strcmp(name, ret->name)) {			return ret;		}		ret = ret->next;	}	return NULL;}static unsigned char *get_attribute_value(struct attributes *attr, unsigned char *name){	struct attributes *attribute;	foreachback (attribute, *attr) {		if (!strcmp(attribute->name, name)) {			return attribute->prev->name;		}	}	return NULL;}static struct tree_node *new_node(struct tree_node *parent){	struct tree_node *node;	node = mem_calloc(1, sizeof(*node));	if (!node) return NULL;	node->parent = parent ? parent : node;	node->attrs = mem_calloc(1, sizeof(*node->attrs));	if (!node->attrs) {		mem_free(node);		return NULL;	}	init_list(*node->attrs);	return node;}static voidfree_node(struct tree_node *node){	struct attributes *attribute;	if (node->attrs) {		foreachback (attribute, *node->attrs)			mem_free_if(attribute->name);		free_list(*(struct list_head *) node->attrs); /* Don't free list during traversal */		mem_free(node->attrs);	}	mem_free_if(node->name);	mem_free_if(node->text);	mem_free(node);}/* Read and write functions for the XBEL backend */struct bookmarks_backend xbel_bookmarks_backend = {	filename_bookmarks_xbel,	read_bookmarks_xbel,	write_bookmarks_xbel,};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -