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

git+ssh://pasky.or.cz/srv/git/elinks.git
This commit is contained in:
Miciah Dashiel Butler Masters 2006-01-30 15:42:03 +00:00 committed by Miciah Dashiel Butler Masters
commit db9768963f
45 changed files with 883 additions and 307 deletions

View File

@ -161,6 +161,9 @@ Doug Kearns <djkea2@mugca.its.monash.edu.au>
Edwin Groothuis <edwin@mavetju.org>
Dump-width option
Eric Wald <eswald@gmail.com>
Vim ftplugin to set ELinks coding style
Evan Hughes <hughes@lab43.org>
Bookmarks

View File

@ -740,13 +740,17 @@ dnl Check for Python
dnl ===================================================================
enable_python="no";
AC_ARG_WITH(python, [ --with-python enable Python support],
AC_ARG_WITH(python, [ --with-python=[prefix] enable Python support],
[
if test "$withval" = yes; then
if test "$withval" != no; then
# FIXME: If withval is a valid directory append it to PATH
# so that you can specify one of several Python installations.
withval="";
enable_python=yes;
if test "$withval" != yes; then
python_prefix="$withval"
else
python_prefix=""
fi
enable_python=yes
cat <<EOF
***********************************************************************
The Python support is incomplete and not so well integrated to ELinks
@ -758,35 +762,46 @@ EOF
fi
])
AC_MSG_CHECKING([for Python])
cf_result=no
EL_SAVE_FLAGS
if test "$enable_python" = "yes"; then
PYTHON_LIBS="-lpython"
PYTHON_CFLAGS="-I`python -c 'from distutils import sysconfig; print sysconfig.get_python_inc()' 2> /dev/null`"
LIBS="$PYTHON_LIBS $LIBS"
CFLAGS="$PYTHON_CFLAGS $CFLAGS"
CPPFLAGS="$CPPFLAGS $PYTHON_CFLAGS"
AC_TRY_LINK([
#include <Python.h>
],
if test -n "$python_prefix" && test -d "$python_prefix/bin"; then
PYTHON_PATH="$python_prefix/bin:$PATH"
else
PYTHON_PATH="$PATH"
fi
AC_PATH_PROG(PYTHON, python, no, $PYTHON_PATH)
if test "$PYTHON" = "no" ; then
cf_result=no
else
PYTHON_CFLAGS="-I`$PYTHON -c 'from distutils import sysconfig; print sysconfig.get_python_inc()' 2> /dev/null`"
if test -n "$python_prefix" && test -d "$python_prefix/lib"; then
PYTHON_LIBS="-L$python_prefix/lib -lpython"
else
PYTHON_LIBS="-lpython"
fi
LIBS="$PYTHON_LIBS $LIBS"
CFLAGS="$PYTHON_CFLAGS $CFLAGS"
AC_TRY_LINK([#include <Python.h>],
[Py_Initialize();],
cf_result=yes, cf_result=no)
if test "$cf_result" != "yes"; then
EL_RESTORE_FLAGS
else
EL_CONFIG(CONFIG_SCRIPTING_PYTHON, [Python])
CFLAGS="$CFLAGS_X"
AC_SUBST(PYTHON_LIBS)
AC_SUBST(PYTHON_CFLAGS)
fi
fi
fi
if test "$cf_result" != "yes"; then
EL_RESTORE_FLAGS
else
EL_CONFIG(CONFIG_SCRIPTING_PYTHON, [Python])
CFLAGS="$CFLAGS_X"
AC_SUBST(PYTHON_LIBS)
AC_SUBST(PYTHON_CFLAGS)
fi
AC_MSG_CHECKING([for Python])
if test "$cf_result"; then AC_MSG_RESULT($cf_result); fi
@ -955,6 +970,7 @@ fi
AC_MSG_RESULT($cf_result)
CONFIG_GNUTLS_OPENSSL_COMPAT=no
dnl ---- GNU TLS
dnl We can't have AC_MSG_CHECKING here, because AC_PATH_PROG prints its own and
dnl it looks ugly then.

View File

@ -0,0 +1,13 @@
If you want to use Python scripting with ELinks add
--with-python to the configure invocation copy hooks.py to ~/.elinks
When your Python installation is your own build, you could give prefix
to the configure, eg.
--with-python=/usr/local when Python binary is placed in /usr/local/bin, etc.
When 'configure' cannot find -lpython make symbolic link to the appropriate
library, eg.
# cd /usr/local/lib
# ln -s libpython2.4.so.1.0 libpython.so
For the present hooks.py is not very usable. You are welcome to make it better.
Good Luck!

View File

@ -1,5 +1,31 @@
def goto_url_hook(url):
return None
dumbprefixes = {
"7th" : "http://7thguard.net/",
"b" : "http://babelfish.altavista.com/babelfish/tr",
"bz" : "http://bugzilla.elinks.cz",
"bug" : "http://bugzilla.elinks.cz",
"d" : "http://www.dict.org",
"g" : "http://www.google.com/",
"gg" : "http://www.google.com/",
"go" : "http://www.google.com/",
"fm" : "http://www.freshmeat.net/",
"sf" : "http://www.sourceforge.net/",
"dbug" : "http://bugs.debian.org/",
"dpkg" : "http://packages.debian.org/",
"pycur" : "http://www.python.org/doc/current/",
"pydev" : "http://www.python.org/dev/doc/devel/",
"pyhelp" : "http://starship.python.net/crew/theller/pyhelp.cgi",
"pyvault" : "http://www.vex.net/parnassus/",
"e2" : "http://www.everything2.org/",
"sd" : "http://www.slashdot.org/"
}
def goto_url_hook(url, current_url):
global dumbprefixes
if dumbprefixes.has_key(url):
return dumbprefixes[url];
else:
return None
def follow_url_hook(url):
return None

View File

@ -2546,7 +2546,7 @@ msgstr "Numerowanie odno
#: src/config/options.inc:306
msgid "Display numbers next to the links."
msgstr "Czy wyświetlać liczby z prawej strony odnośników."
msgstr "Czy wyświetlać numery odnośników."
#: src/config/options.inc:308
msgid "Handling of target=_blank"
@ -3274,7 +3274,7 @@ msgstr "Czy pami
#
#: src/config/options.inc:670
msgid "HTML rendering"
msgstr "Renderowanie HTML-a"
msgstr "Formatowanie HTML-a"
#: src/config/options.inc:672
msgid "Options concerning the display of HTML pages."
@ -3320,7 +3320,7 @@ msgstr "Pokazuj indeks g
#: src/config/options.inc:690
msgid "Rendering of html link element"
msgstr "Renderowanie elementu odnośnika html"
msgstr "Wyświetlanie elementu odnośnika html"
#: src/config/options.inc:692
msgid ""
@ -3332,7 +3332,7 @@ msgid ""
"4 is type in addition\n"
"5 is everything"
msgstr ""
"W jaki sposób renderować znaczniki <link> w nagłówku HTML:\n"
"W jaki sposób pokazywać znaczniki <link> w nagłówku HTML:\n"
"0 - w ogóle\n"
"1 - tytu³\n"
"2 - dodatkowo nazwa\n"
@ -3365,7 +3365,7 @@ msgstr ""
#
#: src/config/options.inc:711
msgid "Plain rendering"
msgstr "Renderowanie zwykłego tekstu"
msgstr "Formatowanie zwykłego tekstu"
#: src/config/options.inc:713
msgid "Options concerning the display of plain text pages."
@ -4388,7 +4388,7 @@ msgstr "Cykliczne zapisywanie"
#. name:
#: src/config/urlhist.c:61
msgid "Goto URL History"
msgstr "Historia globalna"
msgstr "Historia \"Przejdź do URL-a\""
#. name:
#: src/cookies/cookies.c:80 src/cookies/cookies.c:827
@ -5716,7 +5716,7 @@ msgstr "Czy na pewno chcesz skasowa
#: src/globhist/dialogs.c:169
msgid "Search history"
msgstr "Przeszukaj historię"
msgstr "Szukanie w historii"
#
#: src/globhist/dialogs.c:226
@ -8468,7 +8468,7 @@ msgstr "Szukaj wstecz"
#. name:
#: src/viewer/text/search.c:1654
msgid "Search History"
msgstr "Przeszukaj historię"
msgstr "Szukanie w historii"
#: src/viewer/text/textarea.c:332
msgid "You cannot launch an external editor in the anonymous mode."

View File

@ -507,7 +507,7 @@ render_dom_node_enhanced_text(struct dom_renderer *renderer, struct dom_node *no
}
#endif
enum dom_stack_code
static enum dom_stack_code
render_dom_node_source(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_renderer *renderer = stack->current->data;

View File

@ -135,6 +135,10 @@ check_link_word(struct document *document, unsigned char *uri, int length,
if (!where) return NULL;
/* We need to reparse the URI and normalize it so that the protocol and
* host part are converted to lowercase. */
normalize_uri(NULL, where);
new_link = add_document_link(document, where, length, x, y);
if (!new_link) mem_free(where);

View File

@ -1,5 +1,9 @@
/* DOM Configuration */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "elinks.h"
#include "dom/configuration.h"
@ -304,7 +308,7 @@ struct dom_config_info {
};
#define DOM_CONFIG(name, flag) \
{ INIT_DOM_STRING(name, -1), (flag) }
{ STATIC_DOM_STRING(name), (flag) }
static struct dom_config_info dom_config_info[] = {
DOM_CONFIG("cdata-sections", DOM_CONFIG_CDATA_SECTIONS),

View File

@ -55,7 +55,7 @@ static const struct dom_scan_table_info css_scan_table_info[] = {
};
#define CSS_STRING_MAP(str, type, family) \
{ INIT_DOM_STRING(str, -1), CSS_TOKEN_##type, CSS_TOKEN_##family }
{ STATIC_DOM_STRING(str), CSS_TOKEN_##type, CSS_TOKEN_##family }
static const struct dom_scanner_string_mapping css_string_mappings[] = {
CSS_STRING_MAP("Hz", FREQUENCY, DIMENSION),

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;
@ -451,11 +471,11 @@ done_dom_node(struct dom_node *node)
struct dom_string *
get_dom_node_name(struct dom_node *node)
{
static struct dom_string cdata_section_str = INIT_DOM_STRING("#cdata-section", -1);
static struct dom_string comment_str = INIT_DOM_STRING("#comment", -1);
static struct dom_string document_str = INIT_DOM_STRING("#document", -1);
static struct dom_string document_fragment_str = INIT_DOM_STRING("#document-fragment", -1);
static struct dom_string text_str = INIT_DOM_STRING("#text", -1);
static struct dom_string cdata_section_str = STATIC_DOM_STRING("#cdata-section");
static struct dom_string comment_str = STATIC_DOM_STRING("#comment");
static struct dom_string document_str = STATIC_DOM_STRING("#document");
static struct dom_string document_fragment_str = STATIC_DOM_STRING("#document-fragment");
static struct dom_string text_str = STATIC_DOM_STRING("#text");
assert(node);
@ -521,18 +541,18 @@ get_dom_node_type_name(enum dom_node_type type)
{
static struct dom_string dom_node_type_names[DOM_NODES] = {
INIT_DOM_STRING(NULL, 0),
/* DOM_NODE_ELEMENT */ INIT_DOM_STRING("element", -1),
/* DOM_NODE_ATTRIBUTE */ INIT_DOM_STRING("attribute", -1),
/* DOM_NODE_TEXT */ INIT_DOM_STRING("text", -1),
/* DOM_NODE_CDATA_SECTION */ INIT_DOM_STRING("cdata-section", -1),
/* DOM_NODE_ENTITY_REFERENCE */ INIT_DOM_STRING("entity-reference", -1),
/* DOM_NODE_ENTITY */ INIT_DOM_STRING("entity", -1),
/* DOM_NODE_PROCESSING_INSTRUCTION */ INIT_DOM_STRING("proc-instruction", -1),
/* DOM_NODE_COMMENT */ INIT_DOM_STRING("comment", -1),
/* DOM_NODE_DOCUMENT */ INIT_DOM_STRING("document", -1),
/* DOM_NODE_DOCUMENT_TYPE */ INIT_DOM_STRING("document-type", -1),
/* DOM_NODE_DOCUMENT_FRAGMENT */ INIT_DOM_STRING("document-fragment", -1),
/* DOM_NODE_NOTATION */ INIT_DOM_STRING("notation", -1),
/* DOM_NODE_ELEMENT */ STATIC_DOM_STRING("element"),
/* DOM_NODE_ATTRIBUTE */ STATIC_DOM_STRING("attribute"),
/* DOM_NODE_TEXT */ STATIC_DOM_STRING("text"),
/* DOM_NODE_CDATA_SECTION */ STATIC_DOM_STRING("cdata-section"),
/* DOM_NODE_ENTITY_REFERENCE */ STATIC_DOM_STRING("entity-reference"),
/* DOM_NODE_ENTITY */ STATIC_DOM_STRING("entity"),
/* DOM_NODE_PROCESSING_INSTRUCTION */ STATIC_DOM_STRING("proc-instruction"),
/* DOM_NODE_COMMENT */ STATIC_DOM_STRING("comment"),
/* DOM_NODE_DOCUMENT */ STATIC_DOM_STRING("document"),
/* DOM_NODE_DOCUMENT_TYPE */ STATIC_DOM_STRING("document-type"),
/* DOM_NODE_DOCUMENT_FRAGMENT */ STATIC_DOM_STRING("document-fragment"),
/* DOM_NODE_NOTATION */ STATIC_DOM_STRING("notation"),
};
assert(type < DOM_NODES);

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

@ -67,7 +67,7 @@ struct dom_scanner_string_mapping {
};
#define DOM_STRING_MAP(str, type, family) \
{ INIT_DOM_STRING(str, -1), (type), (family) }
{ STATIC_DOM_STRING(str), (type), (family) }
#define DOM_STRING_MAP_END \
{ INIT_DOM_STRING(NULL, 0), 0, 0 }

View File

@ -28,7 +28,7 @@ get_dom_select_pseudo(struct dom_scanner_token *token)
} pseudo_info[] = {
#define INIT_DOM_SELECT_PSEUDO_STRING(str, type) \
{ INIT_DOM_STRING(str, -1), DOM_SELECT_PSEUDO_##type }
{ STATIC_DOM_STRING(str), DOM_SELECT_PSEUDO_##type }
INIT_DOM_SELECT_PSEUDO_STRING("first-line", FIRST_LINE),
INIT_DOM_SELECT_PSEUDO_STRING("first-letter", FIRST_LETTER),

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

@ -44,7 +44,7 @@ static struct dom_scan_table_info sgml_scan_table_info[] = {
};
#define SGML_STRING_MAP(str, type, family) \
{ INIT_DOM_STRING(str, -1), SGML_TOKEN_##type, SGML_TOKEN_##family }
{ STATIC_DOM_STRING(str), SGML_TOKEN_##type, SGML_TOKEN_##family }
static struct dom_scanner_string_mapping sgml_string_mappings[] = {
SGML_STRING_MAP("--", NOTATION_COMMENT, NOTATION),
@ -458,7 +458,8 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
real_length = 0;
} else if (string == scanner->end) {
/* It is incomplete. */
/* It is incomplete so prevent out of bound acess to
* the scanned string. */
} else if (is_sgml_ident(*string)) {
token->string.string = string;
@ -467,7 +468,7 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
real_length = string - token->string.string;
skip_sgml_space(scanner, &string);
if (*string == '>') {
if (string < scanner->end && *string == '>') {
type = SGML_TOKEN_ELEMENT;
string++;
@ -570,7 +571,10 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
string++;
skip_sgml_space(scanner, &string);
if (is_sgml_ident(*string)) {
if (string == scanner->end) {
/* Prevent out of bound access. */
} else if (is_sgml_ident(*string)) {
token->string.string = string;
scan_sgml(scanner, string, SGML_CHAR_IDENT);
real_length = string - token->string.string;
@ -634,7 +638,10 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
* For stricter parsing we should always require attribute
* values to be quoted.
*/
if (*string == '>') {
if (string == scanner->end) {
/* Prevent out of bound access. */
} else if (*string == '>') {
string++;
real_length = 0;
type = SGML_TOKEN_ELEMENT_EMPTY_END;
@ -671,7 +678,8 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
/* Force an incomplete token. */
string = scanner->end;
} else if (is_sgml_attribute(*string)) {
} else if (string < scanner->end
&& is_sgml_attribute(*string)) {
token->string.string++;
scan_sgml_attribute(scanner, string);
type = SGML_TOKEN_ATTRIBUTE;
@ -683,7 +691,8 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
type = SGML_TOKEN_IDENT;
}
if (is_sgml_attribute(*string)) {
if (string < scanner->end
&& is_sgml_attribute(*string)) {
scan_sgml_attribute(scanner, string);
type = SGML_TOKEN_ATTRIBUTE;
if (string[-1] == '/' && string[0] == '>') {

View File

@ -55,10 +55,10 @@ struct sgml_node_info {
{ INIT_DOM_STRING(NULL, doctype##_##nodetype##S - 1), doctype##_##nodetype##_UNKNOWN }
#define SGML_NODE_INFO(doctype, nodetype, name, data) \
{ INIT_DOM_STRING(#name, sizeof(#name) - 1), doctype##_##nodetype##_##name, data }
{ STATIC_DOM_STRING(#name), doctype##_##nodetype##_##name, data }
#define SGML_NODE_INF2(doctype, nodetype, name, ident, data) \
{ INIT_DOM_STRING(ident, sizeof(ident) - 1), doctype##_##nodetype##_##name, data }
{ STATIC_DOM_STRING(ident), doctype##_##nodetype##_##name, data }
#define SGML_NODE_INFO_TYPE(doctype, nodetype, name) doctype##_##nodetype##_##name

View File

@ -3,13 +3,22 @@
#include "util/memory.h"
/* For now DOM has it's own little string library. Mostly because there are
* some memory overhead associated with util/string's block-based allocation
* scheme which is optimized for building strings and quickly dispose of it.
* Also, at some point we need to switch to use mainly UTF-8 strings for DOM
* and it needs to be possible to adapt the string library to that. --jonas */
struct dom_string {
size_t length;
unsigned char *string;
};
#define INIT_DOM_STRING(strvalue, strlength) \
{ (strlength) == -1 ? sizeof(strvalue) - 1 : (strlength), (strvalue) }
{ (strlength), (strvalue) }
#define STATIC_DOM_STRING(strvalue) \
{ sizeof(strvalue) - 1, (strvalue) }
static inline void
set_dom_string(struct dom_string *string, unsigned char *value, size_t length)

View File

@ -38,9 +38,9 @@ main(int argc, char *argv[])
struct sgml_parser *parser;
struct dom_select *select;
enum sgml_document_type doctype = SGML_DOCTYPE_HTML;
struct dom_string uri = INIT_DOM_STRING("dom://test", -1);
struct dom_string source = INIT_DOM_STRING("(no source)", -1);
struct dom_string selector = INIT_DOM_STRING("(no select)", -1);
struct dom_string uri = STATIC_DOM_STRING("dom://test");
struct dom_string source = STATIC_DOM_STRING("(no source)");
struct dom_string selector = STATIC_DOM_STRING("(no select)");
int i;
for (i = 1; i < argc; i++) {

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,10 +266,11 @@ 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 = INIT_DOM_STRING("dom://test", -1);
struct dom_string source = INIT_DOM_STRING("(no source)", -1);
struct dom_string uri = STATIC_DOM_STRING("dom://test");
struct dom_string source = STATIC_DOM_STRING("(no source)");
int i;
for (i = 1; i < argc; i++) {
@ -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

@ -55,5 +55,10 @@ test_output_line_numbers \
7
8' \
8
test_output_line_numbers \
'Check line numbers. (IIII)' \
$'1\r\f 2\v\n 3\r\n 4\t\f 5' \
5
test_done

View File

@ -269,6 +269,7 @@ js_window_open(struct SEE_interpreter *interp, struct SEE_object *self,
*/
#define NUMBER_OF_URLS_TO_REMEMBER 8
static struct {
struct SEE_interpreter *interp;
struct SEE_string *url;
struct SEE_string *target;
} strings[NUMBER_OF_URLS_TO_REMEMBER];
@ -277,12 +278,15 @@ js_window_open(struct SEE_interpreter *interp, struct SEE_object *self,
SEE_ToString(interp, argv[1], &target_value);
for (i = 0; i < NUMBER_OF_URLS_TO_REMEMBER; i++) {
if (!(strings[i].url && strings[i].target))
if (!(strings[i].url && strings[i].target
&& strings[i].interp))
continue;
if (!SEE_string_cmp(url_value.u.string, strings[i].url)
if (strings[i].interp == interp
&& !SEE_string_cmp(url_value.u.string, strings[i].url)
&& !SEE_string_cmp(target_value.u.string, strings[i].target))
return;
}
strings[indeks].interp = interp;
strings[indeks].url = url_value.u.string;
strings[indeks].target = target_value.u.string;
indeks++;

View File

@ -385,17 +385,19 @@ input_select(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval
static JSObject *
get_input_object(JSContext *ctx, JSObject *jsform, struct form_state *fs)
{
if (!fs->ecmascript_obj) {
/* jsform ('form') is input's parent */
/* FIXME: That is NOT correct since the real containing element
* should be its parent, but gimme DOM first. --pasky */
JSObject *jsinput = JS_NewObject(ctx, (JSClass *) &input_class, NULL, jsform);
#if 0
if (fs->ecmascript_obj)
return fs->ecmascript_obj;
#endif
/* jsform ('form') is input's parent */
/* FIXME: That is NOT correct since the real containing element
* should be its parent, but gimme DOM first. --pasky */
JSObject *jsinput = JS_NewObject(ctx, (JSClass *) &input_class, NULL, jsform);
JS_DefineProperties(ctx, jsinput, (JSPropertySpec *) input_props);
JS_DefineFunctions(ctx, jsinput, (JSFunctionSpec *) input_funcs);
JS_SetPrivate(ctx, jsinput, fs);
fs->ecmascript_obj = jsinput;
}
JS_DefineProperties(ctx, jsinput, (JSPropertySpec *) input_props);
JS_DefineFunctions(ctx, jsinput, (JSFunctionSpec *) input_funcs);
JS_SetPrivate(ctx, jsinput, fs);
fs->ecmascript_obj = jsinput;
return fs->ecmascript_obj;
}
@ -815,17 +817,19 @@ form_submit(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
JSObject *
get_form_object(JSContext *ctx, JSObject *jsdoc, struct form_view *fv)
{
if (!fv->ecmascript_obj) {
/* jsdoc ('document') is fv's parent */
/* FIXME: That is NOT correct since the real containing element
* should be its parent, but gimme DOM first. --pasky */
JSObject *jsform = JS_NewObject(ctx, (JSClass *) &form_class, NULL, jsdoc);
#if 0
if (fv->ecmascript_obj)
return fv->ecmascript_obj;
#endif
/* jsdoc ('document') is fv's parent */
/* FIXME: That is NOT correct since the real containing element
* should be its parent, but gimme DOM first. --pasky */
JSObject *jsform = JS_NewObject(ctx, (JSClass *) &form_class, NULL, jsdoc);
JS_DefineProperties(ctx, jsform, (JSPropertySpec *) form_props);
JS_DefineFunctions(ctx, jsform, (JSFunctionSpec *) form_funcs);
JS_SetPrivate(ctx, jsform, fv);
fv->ecmascript_obj = jsform;
}
JS_DefineProperties(ctx, jsform, (JSPropertySpec *) form_props);
JS_DefineFunctions(ctx, jsform, (JSFunctionSpec *) form_funcs);
JS_SetPrivate(ctx, jsform, fv);
fv->ecmascript_obj = jsform;
return fv->ecmascript_obj;
}

View File

@ -310,10 +310,38 @@ window_open(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
if (argc < 1) return JS_TRUE;
url = jsval_to_string(ctx, &argv[0]);
if (argc > 1) {
JSString *url_string = JS_ValueToString(ctx, argv[0]);
JSString *target_string = JS_ValueToString(ctx, argv[1]);
int i;
#define NUMBER_OF_URLS_TO_REMEMBER 8
static struct {
JSContext *ctx;
JSString *url;
JSString *frame;
} strings[NUMBER_OF_URLS_TO_REMEMBER];
static int indeks;
for (i = 0; i < NUMBER_OF_URLS_TO_REMEMBER; i++) {
if (!(strings[i].ctx && strings[i].url && strings[i].frame))
continue;
if (ctx == strings[i].ctx
&& !JS_CompareStrings(url_string, strings[i].url)
&& !JS_CompareStrings(target_string, strings[i].frame))
return JS_TRUE;
}
strings[indeks].ctx = ctx;
strings[indeks].url = JS_InternString(ctx, url);
strings[indeks].frame = JS_InternString(ctx, target);
indeks++;
if (indeks >= NUMBER_OF_URLS_TO_REMEMBER) indeks = 0;
#undef NUMBER_OF_URLS_TO_REMEMBER
}
/* Ratelimit window opening. Recursive window.open() is very nice.
* We permit at most 20 tabs in 2 seconds. The ratelimiter is very
* rough but shall suffice against the usual cases. */
if (!ratelimit_start || time(NULL) - ratelimit_start > 2) {
ratelimit_start = time(NULL);
ratelimit_count = 0;
@ -323,8 +351,6 @@ window_open(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
return JS_TRUE;
}
url = jsval_to_string(ctx, &argv[0]);
/* TODO: Support for window naming and perhaps some window features? */
url = join_urls(doc_view->document->uri,
@ -334,7 +360,6 @@ window_open(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
mem_free(url);
if (!uri) return JS_TRUE;
if (argc > 1) target = jsval_to_string(ctx, &argv[1]);
if (*target && strcasecmp(target, "_blank")) {
struct delayed_open *deo = mem_calloc(1, sizeof(*deo));

View File

@ -224,12 +224,6 @@ get_cache_header_content_type(struct cache_entry *cached)
return NULL;
}
unsigned char *
get_default_content_type(void)
{
return get_default_mime_type();
}
unsigned char *
get_content_type(struct cache_entry *cached)
{

View File

@ -20,9 +20,6 @@ extern struct module mime_module;
* scanning the uri for extensions. */
unsigned char *get_content_type(struct cache_entry *cached);
/* Default mime type */
unsigned char *get_default_content_type(void);
/* Guess content type by looking at configurations of the given @extension */
unsigned char *get_extension_content_type(unsigned char *extension);

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

@ -35,6 +35,30 @@
#include "util/env.h"
#include "util/string.h"
static struct option_info cgi_options[] = {
INIT_OPT_TREE("protocol.file", N_("Local CGI"),
"cgi", 0,
N_("Local CGI specific options.")),
INIT_OPT_STRING("protocol.file.cgi", N_("Path"),
"path", 0, "",
N_("Colon separated list of directories, where CGI scripts are stored.")),
INIT_OPT_BOOL("protocol.file.cgi", N_("Allow local CGI"),
"policy", 0, 0,
N_("Whether to execute local CGI scripts.")),
NULL_OPTION_INFO,
};
struct module cgi_protocol_module = struct_module(
/* name: */ N_("CGI"),
/* options: */ cgi_options,
/* hooks: */ NULL,
/* submodules: */ NULL,
/* data: */ NULL,
/* init: */ NULL,
/* done: */ NULL
);
static void
close_pipe_and_read(struct socket *data_socket)

View File

@ -3,7 +3,9 @@
#define EL__PROTOCOL_FILE_CGI_H
struct connection;
struct module;
extern struct module cgi_protocol_module;
int execute_cgi(struct connection *);
#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"
@ -39,20 +40,6 @@ static struct option_info file_options[] = {
"file", 0,
N_("Options specific to local browsing.")),
#ifdef CONFIG_CGI
INIT_OPT_TREE("protocol.file", N_("Local CGI"),
"cgi", 0,
N_("Local CGI specific options.")),
INIT_OPT_STRING("protocol.file.cgi", N_("Path"),
"path", 0, "",
N_("Colon separated list of directories, where CGI scripts are stored.")),
INIT_OPT_BOOL("protocol.file.cgi", N_("Allow local CGI"),
"policy", 0, 0,
N_("Whether to execute local CGI scripts.")),
#endif /* CONFIG_CGI */
INIT_OPT_BOOL("protocol.file", N_("Allow reading special files"),
"allow_special_files", 0, 0,
N_("Whether to allow reading from non-regular files.\n"
@ -186,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);
@ -200,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;
}
@ -277,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

@ -27,7 +27,6 @@
#include "intl/gettext/libintl.h"
#include "main/module.h"
#include "main/select.h"
#include "mime/mime.h"
#include "network/connection.h"
#include "network/socket.h"
#include "osdep/osdep.h"
@ -82,21 +81,29 @@ compare(FSP_RDENTRY *a, FSP_RDENTRY *b)
return strcmp(a->name, b->name);
}
static void
display_entry(FSP_RDENTRY *fentry, unsigned char dircolor[])
{
printf("%10d\t<a href=\"%s", fentry->size, fentry->name);
if (fentry->type == FSP_RDTYPE_DIR) {
printf("/\">");
if (*dircolor)
printf("<font color=\"%s\"><b>", dircolor);
printf("%s", fentry->name);
if (*dircolor)
printf("</b></font>");
} else {
printf("\">%s", fentry->name);
}
puts("</a>");
}
static void
sort_and_display_entries(FSP_DIR *dir)
sort_and_display_entries(FSP_DIR *dir, unsigned char dircolor[])
{
FSP_RDENTRY fentry, *fresult, *table = NULL;
int size = 0;
int i;
unsigned char dircolor[8];
if (get_opt_bool("document.browse.links.color_dirs")) {
color_to_string(get_opt_color("document.colors.dirs"),
(unsigned char *) &dircolor);
} else {
dircolor[0] = 0;
}
while (!fsp_readdir_native(dir, &fentry, &fresult)) {
FSP_RDENTRY *new_table;
@ -115,14 +122,7 @@ sort_and_display_entries(FSP_DIR *dir)
(int (*)(const void *, const void *)) compare);
for (i = 0; i < size; i++) {
printf("%10d\t<a href=\"%s%s\">", table[i].size, table[i].name,
table[i].type == FSP_RDTYPE_DIR ? "/" : "");
if (table[i].type == FSP_RDTYPE_DIR && *dircolor)
printf("<font color=\"%s\"><b>", dircolor);
printf("%s", table[i].name);
if (table[i].type == FSP_RDTYPE_DIR && *dircolor)
printf("</b></font>");
puts("</a>");
display_entry(&table[i], dircolor);
}
}
@ -131,46 +131,33 @@ 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\">"
"</head><body><h2>FSP directory %s</h2><pre>",
buf.source, uristring, buf.source);
puts(buf.source);
dir = fsp_opendir(ses, data);
if (!dir) goto end;
if (get_opt_bool("document.browse.links.color_dirs")) {
color_to_string(get_opt_color("document.colors.dirs"),
(unsigned char *) &dircolor);
}
if (get_opt_bool("protocol.fsp.sort")) {
sort_and_display_entries(dir);
sort_and_display_entries(dir, dircolor);
} else {
FSP_RDENTRY fentry, *fresult;
unsigned char dircolor[8];
if (get_opt_bool("document.browse.links.color_dirs")) {
color_to_string(get_opt_color("document.colors.dirs"),
(unsigned char *) &dircolor);
} else {
dircolor[0] = 0;
}
while (!fsp_readdir_native(dir, &fentry, &fresult)) {
if (!fresult) break;
printf("%10d\t<a href=\"%s%s\">", fentry.size,
fentry.name, fentry.type == FSP_RDTYPE_DIR ? "/" : "");
if (fentry.type == FSP_RDTYPE_DIR && *dircolor)
printf("<font color=\"%s\"><b>", dircolor);
printf("%s", fentry.name);
if (fentry.type == FSP_RDTYPE_DIR && *dircolor)
printf("</b></font>");
puts("</a>");
display_entry(&fentry, dircolor);
}
fsp_closedir(dir);
}
@ -180,31 +167,6 @@ end:
exit(0);
}
static unsigned char *
get_content_type_uri(struct uri *uri)
{
unsigned char *extension = get_extension_from_uri(uri);
if (extension) {
unsigned char *ctype;
/* XXX: A little hack for making extension handling case
* insensitive. We could probably do it better by making
* guess_encoding() case independent the real problem however
* is with default (via option system) and mimetypes resolving
* doing that option and hash lookup will not be easy to
* convert. --jonas */
convert_to_lowercase(extension, strlen(extension));
ctype = get_extension_content_type(extension);
if (ctype && *ctype) {
return ctype;
}
}
return get_default_content_type();
}
#define READ_SIZE 4096
static void
@ -229,13 +191,18 @@ do_fsp(struct connection *conn)
FSP_FILE *file = fsp_fopen(ses, data, "r");
int r;
fprintf(stderr, "%s", get_content_type_uri(uri));
fclose(stderr);
if (!file)
fsp_error("fsp_fopen error.");
/* Use the default way to find the MIME type, so write an
* 'empty' name, since something needs to be written in order
* to avoid socket errors. */
fprintf(stderr, "%c", '\0');
fclose(stderr);
while ((r = fsp_fread(buf, 1, READ_SIZE, file)) > 0)
fwrite(buf, 1, r, stdout);
fsp_fclose(file);
fsp_close_session(ses);
exit(0);
@ -273,7 +240,6 @@ fsp_got_data(struct socket *socket, struct read_buffer *rb)
static void
fsp_got_header(struct socket *socket, struct read_buffer *rb)
{
int len = rb->length;
struct connection *conn = socket->conn;
struct read_buffer *buf;
@ -285,10 +251,16 @@ fsp_got_header(struct socket *socket, struct read_buffer *rb)
return;
}
socket->state = SOCKET_END_ONCLOSE;
if (len <= 0) goto end;
rb->data[len] = '\0';
mem_free_set(&conn->cached->content_type, stracpy(rb->data));
end:
if (rb->length > 0) {
unsigned char *ctype = memacpy(rb->data, rb->length);
if (ctype && *ctype)
mem_free_set(&conn->cached->content_type, ctype);
else
mem_free_if(ctype);
}
buf = alloc_read_buffer(conn->data_socket);
if (!buf) {
close(socket->fd);

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

@ -29,6 +29,7 @@
#include "protocol/bittorrent/bittorrent.h"
#include "protocol/bittorrent/connection.h"
#include "protocol/data.h"
#include "protocol/file/cgi.h"
#include "protocol/file/file.h"
#include "protocol/finger/finger.h"
#include "protocol/fsp/fsp.h"
@ -275,6 +276,9 @@ static struct module *protocol_submodules[] = {
&bittorrent_protocol_module,
#endif
&file_protocol_module,
#ifdef CONFIG_CGI
&cgi_protocol_module,
#endif
#ifdef CONFIG_FINGER
&finger_protocol_module,
#endif

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. */

View File

@ -5,6 +5,7 @@
#endif
#include "scripting/python/core.h"
#include <Python.h>
#include <stdio.h>
#include <stdlib.h>
@ -17,6 +18,7 @@
#include "util/file.h"
#include "util/string.h"
PyObject *pDict, *pModule;
void

View File

@ -2,12 +2,8 @@
#ifndef EL__SCRIPTING_PYTHON_CORE_H
#define EL__SCRIPTING_PYTHON_CORE_H
#include <Python.h>
struct module;
extern PyObject *pDict, *pModule;
void init_python(struct module *module);
void cleanup_python(struct module *module);

View File

@ -5,6 +5,7 @@
#endif
#include "scripting/python/core.h"
#include <Python.h>
#include "elinks.h"
@ -16,9 +17,13 @@
#include "session/session.h"
#include "util/string.h"
/* The events that will trigger the functions below and what they are expected
* to do is explained in doc/events.txt */
extern PyObject *pDict;
extern PyObject *pModule;
static void
do_script_hook_goto_url(struct session *ses, unsigned char **url)
{
@ -33,7 +38,8 @@ do_script_hook_goto_url(struct session *ses, unsigned char **url)
} else {
str = struri(cur_loc(ses)->vs.uri);
}
pValue = PyObject_CallFunction(pFunc, "s", str);
pValue = PyObject_CallFunction(pFunc, "ss", *url, str);
if (pValue && (pValue != Py_None)) {
const unsigned char *res = PyString_AsString(pValue);
@ -117,7 +123,7 @@ do_script_hook_pre_format_html(unsigned char *url, struct cache_entry *cached,
if (str) {
int len = PyString_Size(pValue); /* strlen(str); */
add_fragment(cached, 0, (unsigned char *) str, len);
add_fragment(cached, 0, str, len);
normalize_cache_entry(cached, len);
}
Py_DECREF(pValue);

View File

@ -63,12 +63,18 @@ current_link_evhook(struct document_view *doc_view, enum script_event_hook_type
if (!doc_view->vs->ecmascript) return -1;
foreach (evhook, *link->event_hooks) {
struct string src = INIT_STRING(evhook->src, strlen(evhook->src));
unsigned char *ret;
if (evhook->type != type) continue;
/* TODO: Some even handlers return a bool. */
if (!ecmascript_eval_boolback(doc_view->vs->ecmascript, &src))
return 0;
ret = evhook->src;
while ((ret = strstr(ret, "return ")))
while (*ret != ' ') *ret++ = ' ';
{
struct string src = INIT_STRING(evhook->src, strlen(evhook->src));
/* TODO: Some even handlers return a bool. */
if (!ecmascript_eval_boolback(doc_view->vs->ecmascript, &src))
return 0;
}
}
return 1;
@ -865,22 +871,18 @@ try_submit_given_form(struct session *ses, struct document_view *doc_view,
if (init_string(&code)) {
struct view_state *vs = doc_view->vs;
struct ecmascript_interpreter *interpreter;
int res = 1;
unsigned char *ret = form->onsubmit;
int res;
if (vs->ecmascript_fragile)
ecmascript_reset_state(vs);
interpreter = vs->ecmascript;
assert(interpreter);
#ifdef CONFIG_ECMASCRIPT_SEE
{
unsigned char *ret = form->onsubmit;
/* SEE and SpiderMonkey do not like return outside
* functions. */
while ((ret = strstr(ret, "return ")))
while (*ret != ' ') *ret++ = ' ';
/* SEE doesn't like return outside functions */
while ((ret = strstr(ret, "return "))) {
while (*ret != ' ') *ret++ = ' ';
}
}
#endif
add_to_string(&code, form->onsubmit);
res = ecmascript_eval_boolback(interpreter, &code);
done_string(&code);