mirror of
https://github.com/rkd77/elinks.git
synced 2024-11-04 08:17:17 -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:
commit
db9768963f
3
AUTHORS
3
AUTHORS
@ -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
|
||||
|
||||
|
62
configure.in
62
configure.in
@ -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.
|
||||
|
13
contrib/python/README.Python
Normal file
13
contrib/python/README.Python
Normal 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!
|
@ -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
|
||||
|
16
po/pl.po
16
po/pl.po
@ -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."
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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),
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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 }
|
||||
|
@ -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),
|
||||
|
@ -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
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);
|
||||
|
||||
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;
|
||||
|
@ -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] == '>') {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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++) {
|
||||
|
@ -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
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: -'
|
||||
|
||||
test_output_equals \
|
||||
'Parse incorrect processing instructions.' \
|
||||
'Parse incorrect processing instructions. (I)' \
|
||||
'<?js<?>-<?<??>-<?xml <=";&?>-<?' \
|
||||
'
|
||||
proc-instruction: js -> <
|
||||
|
@ -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
|
||||
|
@ -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++;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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))) {
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user