1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-12-04 14:46:47 -05:00

Merge with git+ssh://pasky.or.cz/srv/git/elinks.git

This commit is contained in:
2006-01-30 12:42:40 +01:00
commit 41e8570e64
18 changed files with 570 additions and 102 deletions

View File

@ -1,5 +1,9 @@
/* DOM Configuration */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "elinks.h"
#include "dom/configuration.h"

View File

@ -190,7 +190,8 @@ dom_node_list_bsearch(struct dom_node_search *search, struct dom_node_list *list
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 *match = dom_node_list_bsearch(&search, list);
@ -267,6 +268,24 @@ get_dom_node_prev(struct dom_node *node)
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 *
get_dom_node_child(struct dom_node *parent, enum dom_node_type type,
int16_t subtype)
@ -327,6 +346,23 @@ init_dom_node_(unsigned char *file, int line,
node->type = type;
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) {
struct dom_node_list **list = get_dom_node_list(parent, node);
int sort = (type == DOM_NODE_ATTRIBUTE);
@ -342,22 +378,6 @@ init_dom_node_(unsigned char *file, int line,
done_dom_node(node);
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;

View File

@ -111,6 +111,9 @@ struct dom_attribute_node {
* to reduce string comparing and only do one fast find mapping. */
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
* it added from the document source. */
unsigned int specified:1;
@ -124,9 +127,6 @@ struct dom_attribute_node {
/* The attribute value references some other resource */
unsigned int reference:1;
/* The attribute value is delimited by quotes */
unsigned int quoted:1;
};
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. */
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. */
struct dom_node *
get_dom_node_child(struct dom_node *node, enum dom_node_type child_type,

View File

@ -2,6 +2,6 @@ top_builddir=../../..
include $(top_builddir)/Makefile.config
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

170
src/dom/sgml/dump.c Normal file
View 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
View 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

View File

@ -95,7 +95,7 @@ add_sgml_attribute(struct dom_stack *stack,
node->data.attribute.reference = !!(info->flags & SGML_ATTRIBUTE_REFERENCE);
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)
return NULL;

View File

@ -13,6 +13,7 @@
#include "dom/configuration.h"
#include "dom/node.h"
#include "dom/sgml/dump.h"
#include "dom/sgml/parser.h"
#include "dom/stack.h"
@ -265,6 +266,7 @@ main(int argc, char *argv[])
enum sgml_parser_code code = 0;
enum dom_config_flag normalize_flags = 0;
int normalize = 0;
int dump = 0;
int complete = 1;
size_t read_stdin = 0;
struct dom_string uri = STATIC_DOM_STRING("dom://test");
@ -338,6 +340,10 @@ main(int argc, char *argv[])
flags |= SGML_PARSER_INCREMENTAL;
complete = 0;
} else if (!strcmp(arg, "dump")) {
type = SGML_PARSER_TREE;
dump = 1;
} else if (!strcmp(arg, "error")) {
flags |= SGML_PARSER_DETECT_ERRORS;
@ -355,7 +361,7 @@ main(int argc, char *argv[])
parser->error_func = sgml_error_function;
if (normalize)
add_dom_config_normalizer(&parser->stack, normalize_flags);
else
else if (!dump)
add_dom_stack_context(&parser->stack, NULL, &sgml_parser_test_context_info);
if (read_stdin > 0) {
@ -402,7 +408,7 @@ main(int argc, char *argv[])
pop_dom_node(&parser->stack);
}
if (normalize) {
if (normalize || dump) {
struct dom_stack stack;
/* 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
* assumes the parser can be accessed via
* 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);
done_dom_stack(&stack);
done_dom_node(parser->root);

173
src/dom/test/test-sgml-dump-basic Executable file
View 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.' \
'&amp;-&#42;'
#############################################################################
# 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

View File

@ -225,7 +225,7 @@ proc-instruction: ->
#text: -'
test_output_equals \
'Parse incorrect processing instructions.' \
'Parse incorrect processing instructions. (I)' \
'<?js<?>-<?<??>-<?xml <=";&?>-<?' \
'
proc-instruction: js -> <

View File

@ -1,8 +1,6 @@
top_builddir=../..
include $(top_builddir)/Makefile.config
SUBDIRS = auth file http
SUBDIRS-$(CONFIG_BITTORRENT) += bittorrent
SUBDIRS-$(CONFIG_FINGER) += finger
SUBDIRS-$(CONFIG_FSP) += fsp
@ -12,11 +10,10 @@ SUBDIRS-$(CONFIG_NNTP) += nntp
SUBDIRS-$(CONFIG_SMB) += smb
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_CGI) += common.o
OBJS-$(CONFIG_FSP) += common.o
OBJS-$(CONFIG_SMB) += common.o
OBJS = about.o common.o date.o header.o protocol.o proxy.o uri.o user.o
include $(top_srcdir)/Makefile.lib

View File

@ -17,7 +17,13 @@
#include "elinks.h"
#include "config/options.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. */
@ -35,3 +41,103 @@ close_all_non_term_fd(void)
for (n = 3; n < max; 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;
}

View File

@ -1,7 +1,15 @@
#ifndef EL__PROTOCOL_COMMON_H
#define EL__PROTOCOL_COMMON_H
#include "network/state.h"
struct string;
struct uri;
/* Close all non-terminal file descriptors. */
void close_all_non_term_fd(void);
enum connection_state
init_directory_listing(struct string *page, struct uri *uri);
#endif

View File

@ -25,6 +25,7 @@
#include "intl/gettext/libintl.h"
#include "main/module.h"
#include "network/connection.h"
#include "protocol/common.h"
#include "protocol/file/cgi.h"
#include "protocol/file/file.h"
#include "protocol/uri.h"
@ -172,12 +173,12 @@ add_dir_entries(struct directory_entry *entries, unsigned char *dirpath,
* @dirpath. */
/* Returns a connection state. S_OK if all is well. */
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");
unsigned char *slash = dirpath;
unsigned char *pslash = ++slash;
struct directory_entry *entries;
enum connection_state state;
errno = 0;
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;
}
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_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 /");
add_dir_entries(entries, dirpath, page);
/* Make the directory path with links to each subdir. */
while ((slash = strchr(slash, '/'))) {
*slash = 0;
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;
if (!add_to_string(page, "</pre>\n<hr>\n</body>\n</html>\n")) {
done_string(page);
return S_OUT_OF_MEM;
}
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;
}
@ -263,7 +251,7 @@ file_protocol_handler(struct connection *connection)
redirect_location = "/";
state = S_OK;
} else {
state = list_directory(name.source, &page);
state = list_directory(connection, name.source, &page);
type = "text/html";
}

View File

@ -131,21 +131,16 @@ fsp_directory(FSP_SESSION *ses, struct uri *uri)
{
struct string buf;
FSP_DIR *dir;
unsigned char *uristring = get_uri_string(uri, URI_PUBLIC);
unsigned char *data = get_uri_string(uri, URI_DATA);
unsigned char dircolor[8] = "";
if (!uristring || !data || !init_string(&buf))
if (!data || init_directory_listing(&buf, uri) != S_OK)
fsp_error("Out of memory");
fprintf(stderr, "text/html");
fclose(stderr);
add_html_to_string(&buf, uristring, strlen(uristring));
printf("<html><head><title>%s</title><base href=\"%s", buf.source,
uristring);
if (buf.source[buf.length - 1] != '/') printf("/");
printf("\"></head><body><h2>FSP directory %s</h2><pre>", buf.source);
puts(buf.source);
dir = fsp_opendir(ses, data);
if (!dir) goto end;

View File

@ -42,6 +42,7 @@
#include "osdep/osdep.h"
#include "osdep/stat.h"
#include "protocol/auth/auth.h"
#include "protocol/common.h"
#include "protocol/ftp/ftp.h"
#include "protocol/ftp/parse.h"
#include "protocol/uri.h"
@ -1253,37 +1254,21 @@ out_of_mem:
if (ftp->dir && !conn->from) {
struct string string;
unsigned char *uristring;
enum connection_state state;
if (!conn->uri->data) {
abort_connection(conn, S_FTP_ERROR);
return;
}
uristring = get_uri_string(conn->uri, URI_PUBLIC);
if (!uristring) goto out_of_mem;
if (!init_string(&string)) {
mem_free(uristring);
goto out_of_mem;
state = init_directory_listing(&string, conn->uri);
if (state != S_OK) {
abort_connection(conn, state);
return;
}
add_html_to_string(&string, uristring, strlen(uristring));
mem_free(uristring);
#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>");
add_fragment(conn->cached, conn->from, string.source, string.length);
conn->from += string.length;
done_string(&string);
@ -1343,6 +1328,10 @@ out_of_mem:
(unsigned char *) dircolor) == -1)
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>");
close_socket(conn->data_socket);

View File

@ -35,6 +35,7 @@
#include "main/module.h"
#include "network/connection.h"
#include "network/socket.h"
#include "protocol/common.h"
#include "protocol/gopher/gopher.h"
#include "protocol/protocol.h"
#include "protocol/uri.h"
@ -599,25 +600,15 @@ read_gopher_directory_data(struct connection *conn, struct read_buffer *rb)
struct string buffer;
unsigned char *end;
if (!init_string(&buffer))
return S_OUT_OF_MEM;
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,
"<html>\n"
"<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);
} else if (!init_string(&buffer)) {
return S_OUT_OF_MEM;
}
while ((end = get_gopher_line_end(rb->data, rb->length))) {

View File

@ -160,6 +160,9 @@ enum uri_component {
/* Used for HTTP CONNECT method info */
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
* IPv6 hostnames without the brackets because we don't ask for
* URI_PORT. */