mirror of
https://github.com/rkd77/elinks.git
synced 2025-04-18 00:47:36 -04:00
Merge with git+ssh://pasky.or.cz/srv/git/elinks.git
This commit is contained in:
commit
41e8570e64
@ -1,5 +1,9 @@
|
|||||||
/* DOM Configuration */
|
/* DOM Configuration */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "elinks.h"
|
#include "elinks.h"
|
||||||
|
|
||||||
#include "dom/configuration.h"
|
#include "dom/configuration.h"
|
||||||
|
@ -190,7 +190,8 @@ dom_node_list_bsearch(struct dom_node_search *search, struct dom_node_list *list
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_dom_node_map_index(struct dom_node_list *list, struct dom_node *node)
|
int
|
||||||
|
get_dom_node_map_index(struct dom_node_list *list, struct dom_node *node)
|
||||||
{
|
{
|
||||||
struct dom_node_search search = INIT_DOM_NODE_SEARCH(node, list);
|
struct dom_node_search search = INIT_DOM_NODE_SEARCH(node, list);
|
||||||
struct dom_node *match = dom_node_list_bsearch(&search, list);
|
struct dom_node *match = dom_node_list_bsearch(&search, list);
|
||||||
@ -267,6 +268,24 @@ get_dom_node_prev(struct dom_node *node)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct dom_node *
|
||||||
|
get_dom_node_next(struct dom_node *node)
|
||||||
|
{
|
||||||
|
struct dom_node_list **list;
|
||||||
|
int index;
|
||||||
|
|
||||||
|
assert(node->parent);
|
||||||
|
|
||||||
|
list = get_dom_node_list(node->parent, node);
|
||||||
|
if (!list) return NULL;
|
||||||
|
|
||||||
|
index = get_dom_node_list_pos(*list, node);
|
||||||
|
if (index + 1 < (*list)->size)
|
||||||
|
return (*list)->entries[index + 1];
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
struct dom_node *
|
struct dom_node *
|
||||||
get_dom_node_child(struct dom_node *parent, enum dom_node_type type,
|
get_dom_node_child(struct dom_node *parent, enum dom_node_type type,
|
||||||
int16_t subtype)
|
int16_t subtype)
|
||||||
@ -327,6 +346,23 @@ init_dom_node_(unsigned char *file, int line,
|
|||||||
node->type = type;
|
node->type = type;
|
||||||
node->parent = parent;
|
node->parent = parent;
|
||||||
|
|
||||||
|
/* Make it possible to add a node to a parent without allocating the
|
||||||
|
* strings. */
|
||||||
|
if (allocated >= 0) {
|
||||||
|
node->allocated = !!allocated;
|
||||||
|
} else if (parent) {
|
||||||
|
node->allocated = parent->allocated;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->allocated) {
|
||||||
|
if (!init_dom_string(&node->string, string->string, string->length)) {
|
||||||
|
done_dom_node(node);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
copy_dom_string(&node->string, string);
|
||||||
|
}
|
||||||
|
|
||||||
if (parent) {
|
if (parent) {
|
||||||
struct dom_node_list **list = get_dom_node_list(parent, node);
|
struct dom_node_list **list = get_dom_node_list(parent, node);
|
||||||
int sort = (type == DOM_NODE_ATTRIBUTE);
|
int sort = (type == DOM_NODE_ATTRIBUTE);
|
||||||
@ -342,22 +378,6 @@ init_dom_node_(unsigned char *file, int line,
|
|||||||
done_dom_node(node);
|
done_dom_node(node);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make it possible to add a node to a parent without
|
|
||||||
* allocating the strings. */
|
|
||||||
node->allocated = allocated < 0 ? parent->allocated : !!allocated;
|
|
||||||
|
|
||||||
} else if (allocated >= 0) {
|
|
||||||
node->allocated = !!allocated;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->allocated) {
|
|
||||||
if (!init_dom_string(&node->string, string->string, string->length)) {
|
|
||||||
done_dom_node(node);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
copy_dom_string(&node->string, string);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
|
@ -111,6 +111,9 @@ struct dom_attribute_node {
|
|||||||
* to reduce string comparing and only do one fast find mapping. */
|
* to reduce string comparing and only do one fast find mapping. */
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
|
|
||||||
|
/* The attribute value is delimited by quotes. Can be NUL, ' or ". */
|
||||||
|
unsigned char quoted;
|
||||||
|
|
||||||
/* Was the attribute specified in the DTD as a default attribute or was
|
/* Was the attribute specified in the DTD as a default attribute or was
|
||||||
* it added from the document source. */
|
* it added from the document source. */
|
||||||
unsigned int specified:1;
|
unsigned int specified:1;
|
||||||
@ -124,9 +127,6 @@ struct dom_attribute_node {
|
|||||||
|
|
||||||
/* The attribute value references some other resource */
|
/* The attribute value references some other resource */
|
||||||
unsigned int reference:1;
|
unsigned int reference:1;
|
||||||
|
|
||||||
/* The attribute value is delimited by quotes */
|
|
||||||
unsigned int quoted:1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dom_text_node {
|
struct dom_text_node {
|
||||||
@ -242,6 +242,9 @@ int get_dom_node_map_index(struct dom_node_list *list, struct dom_node *node);
|
|||||||
/* Returns the previous sibling to the node. */
|
/* Returns the previous sibling to the node. */
|
||||||
struct dom_node *get_dom_node_prev(struct dom_node *node);
|
struct dom_node *get_dom_node_prev(struct dom_node *node);
|
||||||
|
|
||||||
|
/* Returns the next sibling to the node. */
|
||||||
|
struct dom_node *get_dom_node_next(struct dom_node *node);
|
||||||
|
|
||||||
/* Returns first text node of the element or NULL. */
|
/* Returns first text node of the element or NULL. */
|
||||||
struct dom_node *
|
struct dom_node *
|
||||||
get_dom_node_child(struct dom_node *node, enum dom_node_type child_type,
|
get_dom_node_child(struct dom_node *node, enum dom_node_type child_type,
|
||||||
|
@ -2,6 +2,6 @@ top_builddir=../../..
|
|||||||
include $(top_builddir)/Makefile.config
|
include $(top_builddir)/Makefile.config
|
||||||
|
|
||||||
SUBDIRS = docbook html rss xbel
|
SUBDIRS = docbook html rss xbel
|
||||||
OBJS = sgml.o parser.o scanner.o
|
OBJS = dump.o parser.o scanner.o sgml.o
|
||||||
|
|
||||||
include $(top_srcdir)/Makefile.lib
|
include $(top_srcdir)/Makefile.lib
|
||||||
|
170
src/dom/sgml/dump.c
Normal file
170
src/dom/sgml/dump.c
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
/* SGML generics */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "elinks.h"
|
||||||
|
|
||||||
|
#include "dom/node.h"
|
||||||
|
#include "dom/sgml/dump.h"
|
||||||
|
#include "dom/stack.h"
|
||||||
|
#include "dom/string.h"
|
||||||
|
|
||||||
|
|
||||||
|
static enum dom_stack_code
|
||||||
|
sgml_file_dumper_element_push(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||||
|
{
|
||||||
|
FILE *file = stack->current->data;
|
||||||
|
struct dom_string *string = &node->string;
|
||||||
|
|
||||||
|
fprintf(file, "<%.*s", string->length, string->string);
|
||||||
|
if (!node->data.element.map
|
||||||
|
|| node->data.element.map->size == 0)
|
||||||
|
fprintf(file, ">");
|
||||||
|
|
||||||
|
return DOM_STACK_CODE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum dom_stack_code
|
||||||
|
sgml_file_dumper_element_pop(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||||
|
{
|
||||||
|
FILE *file = stack->current->data;
|
||||||
|
struct dom_string *string = &node->string;
|
||||||
|
|
||||||
|
fprintf(file, "</%.*s>", string->length, string->string);
|
||||||
|
|
||||||
|
return DOM_STACK_CODE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum dom_stack_code
|
||||||
|
sgml_file_dumper_attribute_push(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||||
|
{
|
||||||
|
FILE *file = stack->current->data;
|
||||||
|
struct dom_string *name = &node->string;
|
||||||
|
struct dom_string *value = &node->data.attribute.value;
|
||||||
|
|
||||||
|
if (node->parent->type == DOM_NODE_PROCESSING_INSTRUCTION)
|
||||||
|
return DOM_STACK_CODE_OK;
|
||||||
|
|
||||||
|
fprintf(file, " %.*s", name->length, name->string);
|
||||||
|
|
||||||
|
if (value->string) {
|
||||||
|
if (node->data.attribute.quoted)
|
||||||
|
fprintf(file, "=%c%.*s%c",
|
||||||
|
node->data.attribute.quoted,
|
||||||
|
value->length, value->string,
|
||||||
|
node->data.attribute.quoted);
|
||||||
|
else
|
||||||
|
/* FIXME: 'encode' if the value contains '"'s? */
|
||||||
|
fprintf(file, "=\"%.*s\"", value->length, value->string);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!get_dom_node_next(node))
|
||||||
|
fprintf(file, ">");
|
||||||
|
|
||||||
|
return DOM_STACK_CODE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum dom_stack_code
|
||||||
|
sgml_file_dumper_proc_instruction_push(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||||
|
{
|
||||||
|
FILE *file = stack->current->data;
|
||||||
|
struct dom_string *target = &node->string;
|
||||||
|
struct dom_string *instruction = &node->data.proc_instruction.instruction;
|
||||||
|
|
||||||
|
fprintf(file, "<?%.*s %.*s?>",
|
||||||
|
target->length, target->string,
|
||||||
|
instruction->length, instruction->string);
|
||||||
|
|
||||||
|
return DOM_STACK_CODE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum dom_stack_code
|
||||||
|
sgml_file_dumper_text_push(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||||
|
{
|
||||||
|
FILE *file = stack->current->data;
|
||||||
|
struct dom_string *string = &node->string;
|
||||||
|
|
||||||
|
fprintf(file, "%.*s", string->length, string->string);
|
||||||
|
|
||||||
|
return DOM_STACK_CODE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum dom_stack_code
|
||||||
|
sgml_file_dumper_cdata_section_push(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||||
|
{
|
||||||
|
FILE *file = stack->current->data;
|
||||||
|
struct dom_string *string = &node->string;
|
||||||
|
|
||||||
|
fprintf(file, "<![CDATA[%.*s]]>", string->length, string->string);
|
||||||
|
|
||||||
|
return DOM_STACK_CODE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum dom_stack_code
|
||||||
|
sgml_file_dumper_comment_push(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||||
|
{
|
||||||
|
FILE *file = stack->current->data;
|
||||||
|
struct dom_string *string = &node->string;
|
||||||
|
|
||||||
|
fprintf(file, "<!--%.*s-->", string->length, string->string);
|
||||||
|
|
||||||
|
return DOM_STACK_CODE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum dom_stack_code
|
||||||
|
sgml_file_dumper_entity_ref_push(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||||
|
{
|
||||||
|
FILE *file = stack->current->data;
|
||||||
|
struct dom_string *string = &node->string;
|
||||||
|
|
||||||
|
fprintf(file, "&%.*s;", string->length, string->string);
|
||||||
|
|
||||||
|
return DOM_STACK_CODE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dom_stack_context_info sgml_file_dumper = {
|
||||||
|
/* Object size: */ 0,
|
||||||
|
/* Push: */
|
||||||
|
{
|
||||||
|
/* */ NULL,
|
||||||
|
/* DOM_NODE_ELEMENT */ sgml_file_dumper_element_push,
|
||||||
|
/* DOM_NODE_ATTRIBUTE */ sgml_file_dumper_attribute_push,
|
||||||
|
/* DOM_NODE_TEXT */ sgml_file_dumper_text_push,
|
||||||
|
/* DOM_NODE_CDATA_SECTION */ sgml_file_dumper_cdata_section_push,
|
||||||
|
/* DOM_NODE_ENTITY_REFERENCE */ sgml_file_dumper_entity_ref_push,
|
||||||
|
/* DOM_NODE_ENTITY */ NULL,
|
||||||
|
/* DOM_NODE_PROC_INSTRUCTION */ sgml_file_dumper_proc_instruction_push,
|
||||||
|
/* DOM_NODE_COMMENT */ sgml_file_dumper_comment_push,
|
||||||
|
/* DOM_NODE_DOCUMENT */ NULL,
|
||||||
|
/* DOM_NODE_DOCUMENT_TYPE */ NULL,
|
||||||
|
/* DOM_NODE_DOCUMENT_FRAGMENT */ NULL,
|
||||||
|
/* DOM_NODE_NOTATION */ NULL,
|
||||||
|
},
|
||||||
|
/* Pop: */
|
||||||
|
{
|
||||||
|
/* */ NULL,
|
||||||
|
/* DOM_NODE_ELEMENT */ sgml_file_dumper_element_pop,
|
||||||
|
/* DOM_NODE_ATTRIBUTE */ NULL,
|
||||||
|
/* DOM_NODE_TEXT */ NULL,
|
||||||
|
/* DOM_NODE_CDATA_SECTION */ NULL,
|
||||||
|
/* DOM_NODE_ENTITY_REFERENCE */ NULL,
|
||||||
|
/* DOM_NODE_ENTITY */ NULL,
|
||||||
|
/* DOM_NODE_PROC_INSTRUCTION */ NULL,
|
||||||
|
/* DOM_NODE_COMMENT */ NULL,
|
||||||
|
/* DOM_NODE_DOCUMENT */ NULL,
|
||||||
|
/* DOM_NODE_DOCUMENT_TYPE */ NULL,
|
||||||
|
/* DOM_NODE_DOCUMENT_FRAGMENT */ NULL,
|
||||||
|
/* DOM_NODE_NOTATION */ NULL,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dom_stack_context *
|
||||||
|
add_sgml_file_dumper(struct dom_stack *stack, FILE *file)
|
||||||
|
{
|
||||||
|
return add_dom_stack_context(stack, file, &sgml_file_dumper);
|
||||||
|
}
|
12
src/dom/sgml/dump.h
Normal file
12
src/dom/sgml/dump.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef EL_DOM_SGML_DUMP_H
|
||||||
|
#define EL_DOM_SGML_DUMP_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
struct dom_stack;
|
||||||
|
struct dom_stack_context;
|
||||||
|
|
||||||
|
struct dom_stack_context *
|
||||||
|
add_sgml_file_dumper(struct dom_stack *stack, FILE *file);
|
||||||
|
|
||||||
|
#endif
|
@ -95,7 +95,7 @@ add_sgml_attribute(struct dom_stack *stack,
|
|||||||
node->data.attribute.reference = !!(info->flags & SGML_ATTRIBUTE_REFERENCE);
|
node->data.attribute.reference = !!(info->flags & SGML_ATTRIBUTE_REFERENCE);
|
||||||
|
|
||||||
if (valtoken && valtoken->type == SGML_TOKEN_STRING)
|
if (valtoken && valtoken->type == SGML_TOKEN_STRING)
|
||||||
node->data.attribute.quoted = 1;
|
node->data.attribute.quoted = valtoken->string.string[-1];
|
||||||
|
|
||||||
if (!node || push_dom_node(stack, node) != DOM_STACK_CODE_OK)
|
if (!node || push_dom_node(stack, node) != DOM_STACK_CODE_OK)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include "dom/configuration.h"
|
#include "dom/configuration.h"
|
||||||
#include "dom/node.h"
|
#include "dom/node.h"
|
||||||
|
#include "dom/sgml/dump.h"
|
||||||
#include "dom/sgml/parser.h"
|
#include "dom/sgml/parser.h"
|
||||||
#include "dom/stack.h"
|
#include "dom/stack.h"
|
||||||
|
|
||||||
@ -265,6 +266,7 @@ main(int argc, char *argv[])
|
|||||||
enum sgml_parser_code code = 0;
|
enum sgml_parser_code code = 0;
|
||||||
enum dom_config_flag normalize_flags = 0;
|
enum dom_config_flag normalize_flags = 0;
|
||||||
int normalize = 0;
|
int normalize = 0;
|
||||||
|
int dump = 0;
|
||||||
int complete = 1;
|
int complete = 1;
|
||||||
size_t read_stdin = 0;
|
size_t read_stdin = 0;
|
||||||
struct dom_string uri = STATIC_DOM_STRING("dom://test");
|
struct dom_string uri = STATIC_DOM_STRING("dom://test");
|
||||||
@ -338,6 +340,10 @@ main(int argc, char *argv[])
|
|||||||
flags |= SGML_PARSER_INCREMENTAL;
|
flags |= SGML_PARSER_INCREMENTAL;
|
||||||
complete = 0;
|
complete = 0;
|
||||||
|
|
||||||
|
} else if (!strcmp(arg, "dump")) {
|
||||||
|
type = SGML_PARSER_TREE;
|
||||||
|
dump = 1;
|
||||||
|
|
||||||
} else if (!strcmp(arg, "error")) {
|
} else if (!strcmp(arg, "error")) {
|
||||||
flags |= SGML_PARSER_DETECT_ERRORS;
|
flags |= SGML_PARSER_DETECT_ERRORS;
|
||||||
|
|
||||||
@ -355,7 +361,7 @@ main(int argc, char *argv[])
|
|||||||
parser->error_func = sgml_error_function;
|
parser->error_func = sgml_error_function;
|
||||||
if (normalize)
|
if (normalize)
|
||||||
add_dom_config_normalizer(&parser->stack, normalize_flags);
|
add_dom_config_normalizer(&parser->stack, normalize_flags);
|
||||||
else
|
else if (!dump)
|
||||||
add_dom_stack_context(&parser->stack, NULL, &sgml_parser_test_context_info);
|
add_dom_stack_context(&parser->stack, NULL, &sgml_parser_test_context_info);
|
||||||
|
|
||||||
if (read_stdin > 0) {
|
if (read_stdin > 0) {
|
||||||
@ -402,7 +408,7 @@ main(int argc, char *argv[])
|
|||||||
pop_dom_node(&parser->stack);
|
pop_dom_node(&parser->stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (normalize) {
|
if (normalize || dump) {
|
||||||
struct dom_stack stack;
|
struct dom_stack stack;
|
||||||
|
|
||||||
/* Note, that we cannot free nodes when walking the DOM
|
/* Note, that we cannot free nodes when walking the DOM
|
||||||
@ -412,7 +418,10 @@ main(int argc, char *argv[])
|
|||||||
/* XXX: This context needs to be added first because it
|
/* XXX: This context needs to be added first because it
|
||||||
* assumes the parser can be accessed via
|
* assumes the parser can be accessed via
|
||||||
* stack->contexts[0].data. */
|
* stack->contexts[0].data. */
|
||||||
add_dom_stack_context(&stack, parser, &sgml_parser_test_context_info);
|
if (normalize)
|
||||||
|
add_dom_stack_context(&stack, parser, &sgml_parser_test_context_info);
|
||||||
|
else if (dump)
|
||||||
|
add_sgml_file_dumper(&stack, stdout);
|
||||||
walk_dom_nodes(&stack, parser->root);
|
walk_dom_nodes(&stack, parser->root);
|
||||||
done_dom_stack(&stack);
|
done_dom_stack(&stack);
|
||||||
done_dom_node(parser->root);
|
done_dom_node(parser->root);
|
||||||
|
173
src/dom/test/test-sgml-dump-basic
Executable file
173
src/dom/test/test-sgml-dump-basic
Executable file
@ -0,0 +1,173 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Copyright (c) 2005 Jonas Fonseca
|
||||||
|
#
|
||||||
|
|
||||||
|
test_description='Test dumping of SGML documents.
|
||||||
|
|
||||||
|
Test that DOM documents are consistently dumped to SGML.
|
||||||
|
Note, this also test whether attribute nodes are sorted
|
||||||
|
correctly.
|
||||||
|
'
|
||||||
|
|
||||||
|
. "$TEST_LIB"
|
||||||
|
|
||||||
|
test_sgml_dump_exact () {
|
||||||
|
desc="$1"; shift
|
||||||
|
src="$1"; shift
|
||||||
|
|
||||||
|
sgml-parser --dump --src "$src" > output
|
||||||
|
echo -n "$src" > expected
|
||||||
|
|
||||||
|
test_expect_success "$desc" 'cmp output expected'
|
||||||
|
}
|
||||||
|
|
||||||
|
test_sgml_dump_equals () {
|
||||||
|
desc="$1"; shift
|
||||||
|
src="$1"; shift
|
||||||
|
out="$1"; shift
|
||||||
|
|
||||||
|
sgml-parser --dump --src "$src" > output
|
||||||
|
echo -n "$out" > expected
|
||||||
|
|
||||||
|
test_expect_success "$desc" 'cmp output expected'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
# Parse various SGML node types.
|
||||||
|
|
||||||
|
test_sgml_dump_exact \
|
||||||
|
'Parse a small document.' \
|
||||||
|
'<html><body><p>Hello World!</p></body></html>'
|
||||||
|
|
||||||
|
test_sgml_dump_exact \
|
||||||
|
'Parse an enclosed comment.' \
|
||||||
|
'<root><!-- Hello World! --></root>'
|
||||||
|
|
||||||
|
test_sgml_dump_exact \
|
||||||
|
'Parse comment combinations. (I)' \
|
||||||
|
'<root><!-- <!-- -- > --><!--foo--><!----></root>'
|
||||||
|
|
||||||
|
test_sgml_dump_exact \
|
||||||
|
'Parse comment combinations. (II).' \
|
||||||
|
'<!-- comment -->s<!-->-->t<!----->u'
|
||||||
|
|
||||||
|
test_sgml_dump_exact \
|
||||||
|
'Parse empty comment.' \
|
||||||
|
'<!---->s'
|
||||||
|
|
||||||
|
test_sgml_dump_exact \
|
||||||
|
'Parse an enclosed CDATA section.' \
|
||||||
|
'<root><![CDATA[...] ]>...]]></root>'
|
||||||
|
|
||||||
|
test_sgml_dump_exact \
|
||||||
|
'Parse non-enclosed CDATA section.' \
|
||||||
|
'<![CDATA[...]]>'
|
||||||
|
|
||||||
|
test_sgml_dump_exact \
|
||||||
|
'Parse attributes.' \
|
||||||
|
'<e a="1" b="2" c=""></e>'
|
||||||
|
|
||||||
|
test_sgml_dump_exact \
|
||||||
|
'Parse XML stylesheet processing instructions.' \
|
||||||
|
'<?xml-stylesheet type="text/xsl" href="url"?>'
|
||||||
|
|
||||||
|
test_sgml_dump_exact \
|
||||||
|
'Parse entity references.' \
|
||||||
|
'&-*'
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
# Test tidy up dumping
|
||||||
|
|
||||||
|
test_sgml_dump_equals \
|
||||||
|
'Parse elements.' \
|
||||||
|
'<root><child attr="value" /><child2></><child3 >a</></root>' \
|
||||||
|
'<root><child attr="value"></child><child2></child2><child3>a</child3></root>'
|
||||||
|
|
||||||
|
test_sgml_dump_equals \
|
||||||
|
'Parse attributes with garbage.' \
|
||||||
|
"<root a=b c='d' e'f' g= h i = j k =></root>" \
|
||||||
|
"<root a=\"b\" c='d' g=\"h\" i=\"j\" k></root>"
|
||||||
|
|
||||||
|
test_sgml_dump_equals \
|
||||||
|
'Parse bad comment. (II)' \
|
||||||
|
'<!--a--!>bad comment' \
|
||||||
|
'<!--a-->bad comment'
|
||||||
|
|
||||||
|
test_sgml_dump_equals \
|
||||||
|
'Parse empty notation.' \
|
||||||
|
'<!>s' \
|
||||||
|
's'
|
||||||
|
|
||||||
|
test_sgml_dump_equals \
|
||||||
|
'Parse a bad CDATA section.' \
|
||||||
|
'<![CDATA[...' \
|
||||||
|
'<![CDATA[...]]>'
|
||||||
|
|
||||||
|
test_sgml_dump_equals \
|
||||||
|
'Parse tag soup elements. (I)' \
|
||||||
|
'<parent attr="value" <child:1></><child:2</>a</parent>' \
|
||||||
|
'<parent attr="value"><child:1></child:1><child:2></child:2>a</parent>'
|
||||||
|
|
||||||
|
test_sgml_dump_equals \
|
||||||
|
'Parse tag soup elements. (II)' \
|
||||||
|
'< a >< b < c / >< / >' \
|
||||||
|
'<a><b><c></c></b></a>'
|
||||||
|
|
||||||
|
test_sgml_dump_equals \
|
||||||
|
'Parse attribute with non-quoted values.' \
|
||||||
|
'<root color=#abc path=/to/%61-&\one";files/>...' \
|
||||||
|
'<root color="#abc" path="/to/%61-&\one";files"></root>...'
|
||||||
|
|
||||||
|
# Just how these should be gracefully handled is not clear to me.
|
||||||
|
test_sgml_dump_equals \
|
||||||
|
'Parse badly formatted entity references.' \
|
||||||
|
'& m33p;-&.:-copy;-&;-&#;-&#xx;' \
|
||||||
|
'& m33p;-&.:-copy;-&;-&#;-&#xx;'
|
||||||
|
|
||||||
|
test_sgml_dump_equals \
|
||||||
|
'Parse processing instructions.' \
|
||||||
|
'<?xml encoding="UTF8"?>
|
||||||
|
...
|
||||||
|
<?ecmascript
|
||||||
|
var val=2;
|
||||||
|
?>' \
|
||||||
|
'<?xml encoding="UTF8"?>
|
||||||
|
...
|
||||||
|
<?ecmascript var val=2;
|
||||||
|
?>'
|
||||||
|
|
||||||
|
test_sgml_dump_equals \
|
||||||
|
'Parse XML processing instructions.' \
|
||||||
|
'<?xml version="1.0" />?><?xml />-' \
|
||||||
|
'<?xml version="1.0" />?><?xml />-?>'
|
||||||
|
|
||||||
|
test_sgml_dump_equals \
|
||||||
|
'Parse exotic processing instructions.' \
|
||||||
|
'<?xml ?+>+?>-?>-<?js?>-<??>-' \
|
||||||
|
'<?xml ?+>+?>-?>-<?js ?>-<? ?>-'
|
||||||
|
|
||||||
|
test_sgml_dump_equals \
|
||||||
|
'Parse incorrect processing instructions. (I)' \
|
||||||
|
'<?js<?>-<?<??>-<?xml <=";&?>-<?' \
|
||||||
|
'<?js <?>-<? <??>-<?xml <=";&?>-' \
|
||||||
|
|
||||||
|
test_sgml_dump_equals \
|
||||||
|
'Parse incorrect processing instructions. (II)' \
|
||||||
|
'<?><?' \
|
||||||
|
'<? ><??>'
|
||||||
|
|
||||||
|
test_sgml_dump_equals \
|
||||||
|
'Skip spaces not inside text.' \
|
||||||
|
'<
|
||||||
|
root
|
||||||
|
ns:attr
|
||||||
|
=
|
||||||
|
"value"
|
||||||
|
><?
|
||||||
|
target
|
||||||
|
data?>< / root >' \
|
||||||
|
'<root ns:attr="value"><?target data?></root>'
|
||||||
|
|
||||||
|
test_done
|
@ -225,7 +225,7 @@ proc-instruction: ->
|
|||||||
#text: -'
|
#text: -'
|
||||||
|
|
||||||
test_output_equals \
|
test_output_equals \
|
||||||
'Parse incorrect processing instructions.' \
|
'Parse incorrect processing instructions. (I)' \
|
||||||
'<?js<?>-<?<??>-<?xml <=";&?>-<?' \
|
'<?js<?>-<?<??>-<?xml <=";&?>-<?' \
|
||||||
'
|
'
|
||||||
proc-instruction: js -> <
|
proc-instruction: js -> <
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
top_builddir=../..
|
top_builddir=../..
|
||||||
include $(top_builddir)/Makefile.config
|
include $(top_builddir)/Makefile.config
|
||||||
|
|
||||||
SUBDIRS = auth file http
|
|
||||||
|
|
||||||
SUBDIRS-$(CONFIG_BITTORRENT) += bittorrent
|
SUBDIRS-$(CONFIG_BITTORRENT) += bittorrent
|
||||||
SUBDIRS-$(CONFIG_FINGER) += finger
|
SUBDIRS-$(CONFIG_FINGER) += finger
|
||||||
SUBDIRS-$(CONFIG_FSP) += fsp
|
SUBDIRS-$(CONFIG_FSP) += fsp
|
||||||
@ -12,11 +10,10 @@ SUBDIRS-$(CONFIG_NNTP) += nntp
|
|||||||
SUBDIRS-$(CONFIG_SMB) += smb
|
SUBDIRS-$(CONFIG_SMB) += smb
|
||||||
SUBDIRS-$(CONFIG_URI_REWRITE) += rewrite
|
SUBDIRS-$(CONFIG_URI_REWRITE) += rewrite
|
||||||
|
|
||||||
OBJS = about.o date.o header.o protocol.o proxy.o uri.o user.o
|
SUBDIRS = auth file http
|
||||||
|
|
||||||
OBJS-$(CONFIG_DATA) += data.o
|
OBJS-$(CONFIG_DATA) += data.o
|
||||||
OBJS-$(CONFIG_CGI) += common.o
|
|
||||||
OBJS-$(CONFIG_FSP) += common.o
|
OBJS = about.o common.o date.o header.o protocol.o proxy.o uri.o user.o
|
||||||
OBJS-$(CONFIG_SMB) += common.o
|
|
||||||
|
|
||||||
include $(top_srcdir)/Makefile.lib
|
include $(top_srcdir)/Makefile.lib
|
||||||
|
@ -17,7 +17,13 @@
|
|||||||
|
|
||||||
#include "elinks.h"
|
#include "elinks.h"
|
||||||
|
|
||||||
|
#include "config/options.h"
|
||||||
#include "protocol/common.h"
|
#include "protocol/common.h"
|
||||||
|
#include "protocol/protocol.h"
|
||||||
|
#include "protocol/uri.h"
|
||||||
|
#include "util/conv.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
#include "util/string.h"
|
||||||
|
|
||||||
|
|
||||||
/* Close all non-terminal file descriptors. */
|
/* Close all non-terminal file descriptors. */
|
||||||
@ -35,3 +41,103 @@ close_all_non_term_fd(void)
|
|||||||
for (n = 3; n < max; n++)
|
for (n = 3; n < max; n++)
|
||||||
close(n);
|
close(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum connection_state
|
||||||
|
init_directory_listing(struct string *page, struct uri *uri)
|
||||||
|
{
|
||||||
|
struct string dirpath = NULL_STRING;
|
||||||
|
struct string location = NULL_STRING;
|
||||||
|
unsigned char *info;
|
||||||
|
int local = (uri->protocol == PROTOCOL_FILE);
|
||||||
|
|
||||||
|
if (!init_string(page)
|
||||||
|
|| !init_string(&dirpath)
|
||||||
|
|| !init_string(&location)
|
||||||
|
|| !add_uri_to_string(&dirpath, uri, URI_DATA)
|
||||||
|
|| !add_uri_to_string(&location, uri, URI_DIR_LOCATION))
|
||||||
|
goto out_of_memory;
|
||||||
|
|
||||||
|
if (dirpath.length > 0
|
||||||
|
&& !dir_sep(dirpath.source[dirpath.length - 1])
|
||||||
|
&& !add_char_to_string(&dirpath, '/'))
|
||||||
|
goto out_of_memory;
|
||||||
|
|
||||||
|
if (uri->protocol == PROTOCOL_GOPHER) {
|
||||||
|
/* A little hack to get readable Gopher names. We should find a
|
||||||
|
* way to do it more general. */
|
||||||
|
decode_uri_string(&dirpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!local && !add_char_to_string(&location, '/'))
|
||||||
|
goto out_of_memory;
|
||||||
|
|
||||||
|
if (!add_to_string(page, "<html>\n<head><title>"))
|
||||||
|
goto out_of_memory;
|
||||||
|
|
||||||
|
if (!local && !add_string_to_string(page, &location))
|
||||||
|
goto out_of_memory;
|
||||||
|
|
||||||
|
if (!add_html_to_string(page, dirpath.source, dirpath.length)
|
||||||
|
|| !add_to_string(page, "</title>\n<base href=\"")
|
||||||
|
|| !add_string_to_string(page, &location))
|
||||||
|
goto out_of_memory;
|
||||||
|
|
||||||
|
encode_uri_string(page, dirpath.source, -1, 0);
|
||||||
|
|
||||||
|
if (!add_to_string(page, "\" />\n</head>\n<body>\n<h2>"))
|
||||||
|
goto out_of_memory;
|
||||||
|
|
||||||
|
/* Use module names? */
|
||||||
|
switch (uri->protocol) {
|
||||||
|
case PROTOCOL_FILE:
|
||||||
|
info = "Local";
|
||||||
|
break;
|
||||||
|
case PROTOCOL_FSP:
|
||||||
|
info = "FSP";
|
||||||
|
break;
|
||||||
|
case PROTOCOL_FTP:
|
||||||
|
info = "FTP";
|
||||||
|
break;
|
||||||
|
case PROTOCOL_GOPHER:
|
||||||
|
info = "Gopher";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
info = "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!add_to_string(page, info)
|
||||||
|
|| !add_to_string(page, " directory "))
|
||||||
|
goto out_of_memory;
|
||||||
|
|
||||||
|
if (!local && !add_string_to_string(page, &location))
|
||||||
|
goto out_of_memory;
|
||||||
|
|
||||||
|
/* Make the directory path with links to each subdir. */
|
||||||
|
{
|
||||||
|
unsigned char *slash = dirpath.source;
|
||||||
|
unsigned char *pslash = slash;
|
||||||
|
|
||||||
|
while ((slash = strchr(slash, '/'))) {
|
||||||
|
/* FIXME: htmlesc? At least we should escape quotes. --pasky */
|
||||||
|
if (!add_to_string(page, "<a href=\"")
|
||||||
|
|| !add_string_to_string(page, &location)
|
||||||
|
|| !add_bytes_to_string(page, dirpath.source, slash - dirpath.source)
|
||||||
|
|| !add_to_string(page, "/\">")
|
||||||
|
|| !add_html_to_string(page, pslash, slash - pslash)
|
||||||
|
|| !add_to_string(page, "</a>/"))
|
||||||
|
goto out_of_memory;
|
||||||
|
|
||||||
|
pslash = ++slash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!add_to_string(page, "</h2>\n<pre>")) {
|
||||||
|
out_of_memory:
|
||||||
|
done_string(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
done_string(&dirpath);
|
||||||
|
done_string(&location);
|
||||||
|
|
||||||
|
return page->length > 0 ? S_OK : S_OUT_OF_MEM;
|
||||||
|
}
|
||||||
|
@ -1,7 +1,15 @@
|
|||||||
#ifndef EL__PROTOCOL_COMMON_H
|
#ifndef EL__PROTOCOL_COMMON_H
|
||||||
#define EL__PROTOCOL_COMMON_H
|
#define EL__PROTOCOL_COMMON_H
|
||||||
|
|
||||||
|
#include "network/state.h"
|
||||||
|
|
||||||
|
struct string;
|
||||||
|
struct uri;
|
||||||
|
|
||||||
/* Close all non-terminal file descriptors. */
|
/* Close all non-terminal file descriptors. */
|
||||||
void close_all_non_term_fd(void);
|
void close_all_non_term_fd(void);
|
||||||
|
|
||||||
|
enum connection_state
|
||||||
|
init_directory_listing(struct string *page, struct uri *uri);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "intl/gettext/libintl.h"
|
#include "intl/gettext/libintl.h"
|
||||||
#include "main/module.h"
|
#include "main/module.h"
|
||||||
#include "network/connection.h"
|
#include "network/connection.h"
|
||||||
|
#include "protocol/common.h"
|
||||||
#include "protocol/file/cgi.h"
|
#include "protocol/file/cgi.h"
|
||||||
#include "protocol/file/file.h"
|
#include "protocol/file/file.h"
|
||||||
#include "protocol/uri.h"
|
#include "protocol/uri.h"
|
||||||
@ -172,12 +173,12 @@ add_dir_entries(struct directory_entry *entries, unsigned char *dirpath,
|
|||||||
* @dirpath. */
|
* @dirpath. */
|
||||||
/* Returns a connection state. S_OK if all is well. */
|
/* Returns a connection state. S_OK if all is well. */
|
||||||
static inline enum connection_state
|
static inline enum connection_state
|
||||||
list_directory(unsigned char *dirpath, struct string *page)
|
list_directory(struct connection *conn, unsigned char *dirpath,
|
||||||
|
struct string *page)
|
||||||
{
|
{
|
||||||
int show_hidden_files = get_opt_bool("protocol.file.show_hidden_files");
|
int show_hidden_files = get_opt_bool("protocol.file.show_hidden_files");
|
||||||
unsigned char *slash = dirpath;
|
|
||||||
unsigned char *pslash = ++slash;
|
|
||||||
struct directory_entry *entries;
|
struct directory_entry *entries;
|
||||||
|
enum connection_state state;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
entries = get_directory_entries(dirpath, show_hidden_files);
|
entries = get_directory_entries(dirpath, show_hidden_files);
|
||||||
@ -186,30 +187,17 @@ list_directory(unsigned char *dirpath, struct string *page)
|
|||||||
return S_OUT_OF_MEM;
|
return S_OUT_OF_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!init_string(page)) return S_OUT_OF_MEM;
|
state = init_directory_listing(page, conn->uri);
|
||||||
|
if (state != S_OK)
|
||||||
|
return S_OUT_OF_MEM;
|
||||||
|
|
||||||
add_to_string(page, "<html>\n<head><title>");
|
add_dir_entries(entries, dirpath, page);
|
||||||
add_html_to_string(page, dirpath, strlen(dirpath));
|
|
||||||
add_to_string(page, "</title>\n<base href=\"");
|
|
||||||
encode_uri_string(page, dirpath, -1, 0);
|
|
||||||
add_to_string(page, "\" />\n</head>\n<body>\n<h2>Directory /");
|
|
||||||
|
|
||||||
/* Make the directory path with links to each subdir. */
|
if (!add_to_string(page, "</pre>\n<hr>\n</body>\n</html>\n")) {
|
||||||
while ((slash = strchr(slash, '/'))) {
|
done_string(page);
|
||||||
*slash = 0;
|
return S_OUT_OF_MEM;
|
||||||
add_to_string(page, "<a href=\"");
|
|
||||||
/* FIXME: htmlesc? At least we should escape quotes. --pasky */
|
|
||||||
add_to_string(page, dirpath);
|
|
||||||
add_to_string(page, "/\">");
|
|
||||||
add_html_to_string(page, pslash, strlen(pslash));
|
|
||||||
add_to_string(page, "</a>/");
|
|
||||||
*slash = '/';
|
|
||||||
pslash = ++slash;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
add_to_string(page, "</h2>\n<pre>");
|
|
||||||
add_dir_entries(entries, dirpath, page);
|
|
||||||
add_to_string(page, "</pre>\n<hr>\n</body>\n</html>\n");
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,7 +251,7 @@ file_protocol_handler(struct connection *connection)
|
|||||||
redirect_location = "/";
|
redirect_location = "/";
|
||||||
state = S_OK;
|
state = S_OK;
|
||||||
} else {
|
} else {
|
||||||
state = list_directory(name.source, &page);
|
state = list_directory(connection, name.source, &page);
|
||||||
type = "text/html";
|
type = "text/html";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,21 +131,16 @@ fsp_directory(FSP_SESSION *ses, struct uri *uri)
|
|||||||
{
|
{
|
||||||
struct string buf;
|
struct string buf;
|
||||||
FSP_DIR *dir;
|
FSP_DIR *dir;
|
||||||
unsigned char *uristring = get_uri_string(uri, URI_PUBLIC);
|
|
||||||
unsigned char *data = get_uri_string(uri, URI_DATA);
|
unsigned char *data = get_uri_string(uri, URI_DATA);
|
||||||
unsigned char dircolor[8] = "";
|
unsigned char dircolor[8] = "";
|
||||||
|
|
||||||
if (!uristring || !data || !init_string(&buf))
|
if (!data || init_directory_listing(&buf, uri) != S_OK)
|
||||||
fsp_error("Out of memory");
|
fsp_error("Out of memory");
|
||||||
|
|
||||||
fprintf(stderr, "text/html");
|
fprintf(stderr, "text/html");
|
||||||
fclose(stderr);
|
fclose(stderr);
|
||||||
add_html_to_string(&buf, uristring, strlen(uristring));
|
|
||||||
|
|
||||||
printf("<html><head><title>%s</title><base href=\"%s", buf.source,
|
puts(buf.source);
|
||||||
uristring);
|
|
||||||
if (buf.source[buf.length - 1] != '/') printf("/");
|
|
||||||
printf("\"></head><body><h2>FSP directory %s</h2><pre>", buf.source);
|
|
||||||
|
|
||||||
dir = fsp_opendir(ses, data);
|
dir = fsp_opendir(ses, data);
|
||||||
if (!dir) goto end;
|
if (!dir) goto end;
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
#include "osdep/osdep.h"
|
#include "osdep/osdep.h"
|
||||||
#include "osdep/stat.h"
|
#include "osdep/stat.h"
|
||||||
#include "protocol/auth/auth.h"
|
#include "protocol/auth/auth.h"
|
||||||
|
#include "protocol/common.h"
|
||||||
#include "protocol/ftp/ftp.h"
|
#include "protocol/ftp/ftp.h"
|
||||||
#include "protocol/ftp/parse.h"
|
#include "protocol/ftp/parse.h"
|
||||||
#include "protocol/uri.h"
|
#include "protocol/uri.h"
|
||||||
@ -1253,37 +1254,21 @@ out_of_mem:
|
|||||||
|
|
||||||
if (ftp->dir && !conn->from) {
|
if (ftp->dir && !conn->from) {
|
||||||
struct string string;
|
struct string string;
|
||||||
unsigned char *uristring;
|
enum connection_state state;
|
||||||
|
|
||||||
if (!conn->uri->data) {
|
if (!conn->uri->data) {
|
||||||
abort_connection(conn, S_FTP_ERROR);
|
abort_connection(conn, S_FTP_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uristring = get_uri_string(conn->uri, URI_PUBLIC);
|
state = init_directory_listing(&string, conn->uri);
|
||||||
if (!uristring) goto out_of_mem;
|
if (state != S_OK) {
|
||||||
|
abort_connection(conn, state);
|
||||||
if (!init_string(&string)) {
|
return;
|
||||||
mem_free(uristring);
|
|
||||||
goto out_of_mem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
add_html_to_string(&string, uristring, strlen(uristring));
|
add_fragment(conn->cached, conn->from, string.source, string.length);
|
||||||
mem_free(uristring);
|
conn->from += string.length;
|
||||||
|
|
||||||
#define ADD_CONST(str) { \
|
|
||||||
add_fragment(conn->cached, conn->from, str, sizeof(str) - 1); \
|
|
||||||
conn->from += (sizeof(str) - 1); }
|
|
||||||
|
|
||||||
#define ADD_STRING() { \
|
|
||||||
add_fragment(conn->cached, conn->from, string.source, string.length); \
|
|
||||||
conn->from += string.length; }
|
|
||||||
|
|
||||||
ADD_CONST("<html>\n<head><title>");
|
|
||||||
ADD_STRING();
|
|
||||||
ADD_CONST("</title></head>\n<body>\n<h2>FTP directory ");
|
|
||||||
ADD_STRING();
|
|
||||||
ADD_CONST("</h2>\n<pre>");
|
|
||||||
|
|
||||||
done_string(&string);
|
done_string(&string);
|
||||||
|
|
||||||
@ -1343,6 +1328,10 @@ out_of_mem:
|
|||||||
(unsigned char *) dircolor) == -1)
|
(unsigned char *) dircolor) == -1)
|
||||||
goto out_of_mem;
|
goto out_of_mem;
|
||||||
|
|
||||||
|
#define ADD_CONST(str) { \
|
||||||
|
add_fragment(conn->cached, conn->from, str, sizeof(str) - 1); \
|
||||||
|
conn->from += (sizeof(str) - 1); }
|
||||||
|
|
||||||
if (ftp->dir) ADD_CONST("</pre>\n<hr>\n</body>\n</html>");
|
if (ftp->dir) ADD_CONST("</pre>\n<hr>\n</body>\n</html>");
|
||||||
|
|
||||||
close_socket(conn->data_socket);
|
close_socket(conn->data_socket);
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include "main/module.h"
|
#include "main/module.h"
|
||||||
#include "network/connection.h"
|
#include "network/connection.h"
|
||||||
#include "network/socket.h"
|
#include "network/socket.h"
|
||||||
|
#include "protocol/common.h"
|
||||||
#include "protocol/gopher/gopher.h"
|
#include "protocol/gopher/gopher.h"
|
||||||
#include "protocol/protocol.h"
|
#include "protocol/protocol.h"
|
||||||
#include "protocol/uri.h"
|
#include "protocol/uri.h"
|
||||||
@ -599,25 +600,15 @@ read_gopher_directory_data(struct connection *conn, struct read_buffer *rb)
|
|||||||
struct string buffer;
|
struct string buffer;
|
||||||
unsigned char *end;
|
unsigned char *end;
|
||||||
|
|
||||||
if (!init_string(&buffer))
|
|
||||||
return S_OUT_OF_MEM;
|
|
||||||
|
|
||||||
if (conn->from == 0) {
|
if (conn->from == 0) {
|
||||||
unsigned char *where = get_uri_string(conn->uri, URI_PUBLIC);
|
enum connection_state state;
|
||||||
|
|
||||||
if (where) decode_uri_for_display(where);
|
state = init_directory_listing(&buffer, conn->uri);
|
||||||
|
if (state != S_OK)
|
||||||
|
return state;
|
||||||
|
|
||||||
add_format_to_string(&buffer,
|
} else if (!init_string(&buffer)) {
|
||||||
"<html>\n"
|
return S_OUT_OF_MEM;
|
||||||
"<head>\n"
|
|
||||||
"<title>Gopher menu at %s</title>\n"
|
|
||||||
"</head>\n"
|
|
||||||
"<body>\n"
|
|
||||||
"<h1>Gopher menu at %s</h1>\n"
|
|
||||||
"<pre>",
|
|
||||||
empty_string_or_(where), empty_string_or_(where));
|
|
||||||
|
|
||||||
mem_free_if(where);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((end = get_gopher_line_end(rb->data, rb->length))) {
|
while ((end = get_gopher_line_end(rb->data, rb->length))) {
|
||||||
|
@ -160,6 +160,9 @@ enum uri_component {
|
|||||||
/* Used for HTTP CONNECT method info */
|
/* Used for HTTP CONNECT method info */
|
||||||
URI_HTTP_CONNECT = URI_HOST | URI_PORT | URI_DEFAULT_PORT,
|
URI_HTTP_CONNECT = URI_HOST | URI_PORT | URI_DEFAULT_PORT,
|
||||||
|
|
||||||
|
/* Used for adding directory listing HTML header, */
|
||||||
|
URI_DIR_LOCATION = URI_PROTOCOL | URI_HOST | URI_PORT | URI_IDN,
|
||||||
|
|
||||||
/* Used for getting the host of a DNS query. As a hidden bonus we get
|
/* Used for getting the host of a DNS query. As a hidden bonus we get
|
||||||
* IPv6 hostnames without the brackets because we don't ask for
|
* IPv6 hostnames without the brackets because we don't ask for
|
||||||
* URI_PORT. */
|
* URI_PORT. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user