1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-12-04 14:46:47 -05:00
This commit is contained in:
Kalle Olavi Niemitalo 2006-02-05 17:48:43 +02:00 committed by Kalle Olavi Niemitalo
commit b1f8756c59
226 changed files with 4412 additions and 1534 deletions

1
.gitignore vendored
View File

@ -13,6 +13,7 @@ depcomp
autom4te.cache
stamp-h1
.deps
.vimrc
elinks
*.swp
*.patch

6
.vimrc
View File

@ -1,6 +0,0 @@
:set shiftwidth=8
:set tabstop=8
:set softtabstop=0
:set noexpandtab
au BufNewFile,BufRead *.inc setf c

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

@ -26,9 +26,7 @@ from GIT in it, use the command:
$ cg clone -s check_file_SITES_for_value_of_this
Note that if you obtained the sources directly from GIT, you NEED to run
./autogen.sh! (It should be enough to do it once - however, if you have build
problems, try running this first.) Also, you obviously need GNU make and
autoconf installed on your system (note that autoconf-2.13 is supported, newer
ones may cause problems thanks to the autoconf developers who don't know how to

View File

@ -43,12 +43,10 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
TEST_LIB=$(top_srcdir)/test/libtest.sh
export TEST_LIB
host = @host@
ASCIIDOC = @ASCIIDOC@
ASCIIDOC_FLAGS = @ASCIIDOC_FLAGS@
AWK = @AWK@
CATALOGS = @CATALOGS@
CC = @CC@
@ -114,7 +112,9 @@ CONFIG_EXMODE = @CONFIG_EXMODE@
CONFIG_FASTMEM = @CONFIG_FASTMEM@
CONFIG_FINGER = @CONFIG_FINGER@
CONFIG_FORMHIST = @CONFIG_FORMHIST@
CONFIG_FSP = @CONFIG_FSP@
CONFIG_FTP = @CONFIG_FTP@
CONFIG_GC = @CONFIG_GC@
CONFIG_GLOBHIST = @CONFIG_GLOBHIST@
CONFIG_GNUTLS = @CONFIG_GNUTLS@
CONFIG_GNUTLS_OPENSSL_COMPAT = @CONFIG_GNUTLS_OPENSSL_COMPAT@
@ -130,7 +130,6 @@ CONFIG_LEDS = @CONFIG_LEDS@
CONFIG_MAILCAP = @CONFIG_MAILCAP@
CONFIG_MANUAL = @CONFIG_MANUAL@
CONFIG_MARKS = @CONFIG_MARKS@
CONFIG_MD5 = @CONFIG_MD5@
CONFIG_MIMETYPES = @CONFIG_MIMETYPES@
CONFIG_MOUSE = @CONFIG_MOUSE@
CONFIG_NNTP = @CONFIG_NNTP@
@ -143,7 +142,6 @@ CONFIG_OS_UNIX = @CONFIG_OS_UNIX@
CONFIG_OS_WIN32 = @CONFIG_OS_WIN32@
CONFIG_OWN_LIBC = @CONFIG_OWN_LIBC@
CONFIG_POD2HTML = @CONFIG_POD2HTML@
CONFIG_SCANNER = @CONFIG_SCANNER@
CONFIG_SCRIPTING = @CONFIG_SCRIPTING@
CONFIG_SCRIPTING_GUILE = @CONFIG_SCRIPTING_GUILE@
CONFIG_SCRIPTING_LUA = @CONFIG_SCRIPTING_LUA@
@ -151,7 +149,6 @@ CONFIG_SCRIPTING_PERL = @CONFIG_SCRIPTING_PERL@
CONFIG_SCRIPTING_PYTHON = @CONFIG_SCRIPTING_PYTHON@
CONFIG_SCRIPTING_RUBY = @CONFIG_SCRIPTING_RUBY@
CONFIG_SCRIPTING_SPIDERMONKEY = @CONFIG_SCRIPTING_SPIDERMONKEY@
CONFIG_SHA1 = @CONFIG_SHA1@
CONFIG_SMALL = @CONFIG_SMALL@
CONFIG_SMB = @CONFIG_SMB@
CONFIG_SPIDERMONKEY = @CONFIG_SPIDERMONKEY@

View File

@ -48,7 +48,7 @@ quiet_cmd_ld_objs = " [$(LD_COLOR)LD$(END_COLOR)] $(RELPATH)$@"
`test -e $(subdir)/$(LIB_O_NAME) && echo $(subdir)/$(LIB_O_NAME)`)
quiet_cmd_link = ' [$(LINK_COLOR)LINK$(END_COLOR)] $(RELPATH)$@'
cmd_link = $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(2) $(LIBS)
cmd_link = $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
quiet_cmd_sparse = ' [SPARSE] $(RELPATH)$(2)'
cmd_sparse = $(SPARSE) $(DEFS) $(INCLUDES) $(AM_CFLAGS) $(CFLAGS) $(SPARSE_FLAGS) $(2)
@ -78,9 +78,10 @@ INCLUDE_ALL=1
endif
ifneq ($(findstring init,$(MAKECMDGOALS)),)
# FIXME: Detect when $(subdir)/Makefile is $(srcdir)/$(subdir)/Makefile
# and error out so the user won't overwrite the 'master' Makefiles.
INCLUDE_ALL=1
ifndef SRC
SRC = $(shell cd $(top_srcdir) && pwd)
endif
endif
ifdef INCLUDE_ALL
@ -92,7 +93,8 @@ endif
#############################################################################
# Internal build rules
# All files in $(OBJS) and any $(subdir)/lib.o are linked into lib.o
# All files in $(OBJS) and any $(subdir)/lib.o are linked into lib.o.
# Sort them to filter out duplicated and get uniform order.
LIB_O_DEPS = \
$(sort $(filter-out $(LIB_O_NAME),$(OBJS))) \
$(foreach subdir,$(sort $(SUBDIRS)),$(wildcard $(subdir)/$(LIB_O_NAME)))
@ -106,7 +108,7 @@ DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
ifneq ($(strip $(OBJS)),)
-include $(DEP_FILES)
OBJS += $(LIB_O_NAME)
ALL_OBJS = $(LIB_O_DEPS) $(LIB_O_NAME)
endif
%.o: $(srcdir)%.c
@ -125,7 +127,7 @@ CLEAN += $(PROG) $(OBJS)
#############################################################################
# The main default rules
all-default: $(OBJS) $(PROGS) $(MAN1) $(MAN5)
all-default: $(ALL_OBJS) $(PROGS) $(MAN1) $(MAN5)
# Ensure that Makefiles in subdirs are created before we recursive into them
init-recursive: init-default
@ -133,7 +135,8 @@ init-recursive: init-default
init-default:
@$(foreach subdir,$(sort $(SUBDIRS)), \
$(MKINSTALLDIRS) $(subdir) >/dev/null; \
echo 'include $(SRC)/$(RELPATH)/$(subdir)/Makefile' > $(subdir)/Makefile;)
test -e "$(subdir)/Makefile" \
|| echo 'include $(SRC)/$(RELPATH)/$(subdir)/Makefile' > $(subdir)/Makefile;)
clean-default cleanall-default:
@-test -z "$(CLEAN)" || $(RM) $(CLEAN)
@ -161,7 +164,6 @@ ifdef MAN5
$(call ncmd,installdata,$(file),$(DESTDIR)$(mandir)/man5);)
endif
##############################################################################
# Auto-testing infrastructure
@ -171,13 +173,16 @@ ifdef TEST_PROGS
TESTDEPS-$(CONFIG_DEBUG) += $(top_builddir)/src/util/memdebug.o
TESTDEPS += $(TESTDEPS-yes)
TEST_LIB=$(top_srcdir)/test/libtest.sh
export TEST_LIB
# This is a very general rule but as long as we don't put test programs in src/
# it should work.
%: %.o $(TESTDEPS)
$(call cmd,link)
TESTS = $(wildcard $(srcdir)test-*)
$(TEST_PROGS): $(TESTDEPS)
$(call cmd,link,$@.o)
# We cannot use $$@.o in the rule above so ensure that all test programs are
# built before linking.
$(TESTS): $(addsuffix .o,$(TEST_PROGS)) $(TEST_PROGS)
@echo "*** $(notdir $@) ***"; \
$(call shellquote,$(SHELL)) $@ $(TEST_OPTS)

7
NEWS
View File

@ -5,6 +5,13 @@ You can see the complete list of recent changes, bugfixes and new features in
the link:http://pasky.or.cz/gitweb.cgi[gitweb interface]. See the ChangeLog
file for details.
ELinks now:
-----------
* Native FSP protocol support (replaces CGI program in contrib/fsp/)
* SEE Ecmascript backend
* Minimalistic RSS renderer
ELinks 0.11.0 (Elated):
-----------------------

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../.vimrc

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../../.vimrc

View File

@ -90,16 +90,17 @@ if test "$CONFIG_SCRIPTING_RUBY" = "yes"; then
fi
fi
EL_RESTORE_FLAGS
if test "$CONFIG_SCRIPTING_RUBY" != "yes"; then
if test -n "$CONFIG_SCRIPTING_RUBY_WITHVAL" &&
test "$CONFIG_SCRIPTING_RUBY_WITHVAL" != no; then
AC_MSG_ERROR([Ruby not found])
fi
EL_RESTORE_FLAGS
else
EL_CONFIG(CONFIG_SCRIPTING_RUBY, [Ruby])
CFLAGS="$CFLAGS_X"
LIBS="$LIBS $RUBY_LIBS"
AC_SUBST(RUBY_CFLAGS)
AC_SUBST(RUBY_LIBS)
fi

View File

@ -66,6 +66,12 @@ if test "x$CONFIG_DOC" != xno; then
EL_CONFIG(CONFIG_ASCIIDOC, [AsciiDoc])
EL_CONFIG(MANUAL_ASCIIDOC, [HTML (one file)])
EL_CONFIG(MAN_ASCIIDOC, [HTML])
echo > config.asciidoc-unsafe.txt
if "$ASCIIDOC" --unsafe config.asciidoc-unsafe.txt >&/dev/null; then
ASCIIDOC_FLAGS=--unsafe
fi
rm config.asciidoc-unsafe.*
fi
AC_PATH_PROGS(XMLTO, "xmlto")
@ -87,6 +93,7 @@ if test "x$CONFIG_DOC" != xno; then
fi
fi
AC_SUBST(ASCIIDOC_FLAGS)
AC_SUBST(CONFIG_ASCIIDOC)
AC_SUBST(CONFIG_POD2HTML)
AC_SUBST(CONFIG_XMLTO)
@ -388,9 +395,22 @@ AC_DEFUN([EL_CHECK_OPTIONAL_LIBRARY],
AC_MSG_RESULT(yes)
EL_SAVE_FLAGS
if test -n "$withval" && test -d "$withval"; then
CFLAGS="$CFLAGS -I$withval/include";
CPPFLAGS="$CPPFLAGS -I$withval/include";
LDFLAGS="$LDFLAGS -L$withval/lib";
# Be a little more careful when setting
# include and lib directories. This way
# $withval will work when includes are
# there but the library is in the common
# /usr/lib ... Does the right thing when
# looking for gc on Debian.
if test -d "$withval/include"; then
CFLAGS="$CFLAGS -I$withval/include"
CPPFLAGS="$CPPFLAGS -I$withval/include"
else
CFLAGS="$CFLAGS -I$withval"
CPPFLAGS="$CPPFLAGS -I$withval"
fi
if test -d "$withval/lib"; then
LDFLAGS="$LDFLAGS -L$withval/lib"
fi
fi
AC_CHECK_HEADERS([$3], [$1=yes], [$1=no; break;])
@ -439,6 +459,11 @@ EL_CONFIG_OPTIONAL_LIBRARY(CONFIG_BZIP2, bzlib, bzlib.h, bz2, BZ2_bzReadOpen,
EL_CONFIG_OPTIONAL_LIBRARY(CONFIG_IDN, idn, idna.h, idn, stringprep_check_version,
[ --without-idn disable international domain names support])
if test "x{with_gc}" != xno; then
EL_CONFIG_OPTIONAL_LIBRARY(CONFIG_GC, gc, gc.h, gc, GC_init,
[ --with-gc enable Boehm's garbage collector])
fi
dnl ===================================================================
dnl Bookmark and XBEL support
dnl ===================================================================
@ -507,6 +532,8 @@ AC_ARG_WITH(see, [ --with-see enable Simple Ecmascript Engine (SEE
AC_MSG_CHECKING([for SEE])
CONFIG_ECMASCRIPT_SEE=no
if test "$enable_see" = "yes"; then
AC_MSG_RESULT(yes);
## Based on the SEE_FLAGS macro.
@ -529,7 +556,6 @@ if test "$enable_see" = "yes"; then
CPPFLAGS="$CPPFLAGS $SEE_CFLAGS"
EL_CONFIG(CONFIG_ECMASCRIPT_SEE, [SEE])
AC_SUBST(SEE_CFLAGS)
AC_SUBST(CONFIG_ECMASCRIPT_SEE)
else
if test -n "$withval" && test "x$withval" != xno; then
AC_MSG_ERROR([SEE not found])
@ -583,26 +609,19 @@ if test -z "$disable_spidermonkey"; then
fi
AC_MSG_RESULT($cf_result)
CONFIG_SPIDERMONKEY="$cf_result"
EL_RESTORE_FLAGS
if test "$cf_result" != yes; then
EL_RESTORE_FLAGS
else
EL_CONFIG(CONFIG_SPIDERMONKEY, [SpiderMonkey])
CFLAGS="$CFLAGS_X"
AC_SUBST(SPIDERMONKEY_LIBS)
AC_SUBST(SPIDERMONKEY_CFLAGS)
fi
if test "$CONFIG_SPIDERMONKEY" = yes &&
test "$CONFIG_ECMASCRIPT_SEE" != yes; then
if test "x$CONFIG_SPIDERMONKEY" = xyes &&
test "x$CONFIG_ECMASCRIPT_SEE" != xyes; then
EL_CONFIG(CONFIG_ECMASCRIPT_SMJS, [SpiderMonkey document scripting])
else
CONFIG_ECMASCRIPT_SMJS=no
fi
AC_SUBST(CONFIG_SPIDERMONKEY)
AC_SUBST(CONFIG_ECMASCRIPT_SMJS)
EL_CONFIG_DEPENDS(CONFIG_ECMASCRIPT, [CONFIG_ECMASCRIPT_SEE CONFIG_ECMASCRIPT_SMJS], [ECMAScript (JavaScript)])
AC_SUBST(CONFIG_ECMASCRIPT_SEE)
AC_SUBST(CONFIG_ECMASCRIPT_SMJS)
dnl ===================================================================
@ -621,6 +640,13 @@ else
CONFIG_SCRIPTING_SPIDERMONKEY=no
fi
if test "x$CONFIG_ECMASCRIPT_SMJS" = xyes ||
test "x$CONFIG_SCRIPTING_SPIDERMONKEY" = xyes; then
LIBS="$LIBS $SPIDERMONKEY_LIBS"
AC_SUBST(SPIDERMONKEY_LIBS)
AC_SUBST(SPIDERMONKEY_CFLAGS)
AC_SUBST(CONFIG_SPIDERMONKEY)
fi
dnl ===================================================================
dnl Check for Guile, optional even if installed.
@ -732,13 +758,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
@ -750,35 +780,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
@ -947,6 +988,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.
@ -1132,6 +1174,34 @@ EL_ARG_DEPEND(CONFIG_CGI, cgi, [HAVE_SETENV_OR_PUTENV:yes], [Local CGI],
EL_ARG_ENABLE(CONFIG_FINGER, finger, [Finger protocol],
[ --enable-finger enable finger protocol support])
dnl ===================================================================
dnl FSP protocol
dnl ===================================================================
EL_SAVE_FLAGS
if test "x${enable_fsp}" != xno; then
AC_CHECK_HEADERS(fsplib.h, HAVE_FSPLIB=yes, HAVE_FSPLIB=no)
if test "$HAVE_FSPLIB" = yes; then
AC_CHECK_LIB(fsplib, fsp_open_session, HAVE_FSPLIB=yes, HAVE_FSPLIB=no)
if test "$HAVE_FSPLIB" = yes; then
LIBS="$LIBS -lfsplib"
else
AC_CHECK_LIB(fsp, fsp_open_session, HAVE_FSPLIB=yes, HAVE_FSPLIB=no)
if test "$HAVE_FSPLIB" = yes; then
LIBS="$LIBS -lfsp"
fi
fi
fi
fi
EL_ARG_DEPEND(CONFIG_FSP, fsp, [HAVE_FSPLIB:yes], [FSP protocol],
[ --enable-fsp enable FSP protocol support])
if test "x$CONFIG_FSP" = xno; then
EL_RESTORE_FLAGS
fi
EL_ARG_ENABLE(CONFIG_FTP, ftp, [FTP protocol],
[ --disable-ftp disable ftp protocol support])
@ -1201,35 +1271,6 @@ EL_ARG_ENABLE(CONFIG_OWN_LIBC, own-libc, [Own libc stubs],
EL_ARG_ENABLE(CONFIG_SMALL, small, [Small binary],
[ --enable-small reduce binary size as far as possible (but see the bottom of doc/small.txt!)])
if test "$CONFIG_OPENSSL" != yes &&
test "$CONFIG_GNUTLS_OPENSSL_COMPAT" != yes ||
test "$CONFIG_OWN_LIBC" = yes;
then
AC_MSG_CHECKING(for built-in MD5 support)
AC_MSG_RESULT(yes)
EL_CONFIG(CONFIG_MD5, [Built-in MD5])
fi
AC_SUBST(CONFIG_MD5)
if test "$CONFIG_BITTORRENT" = yes; then
if test "$CONFIG_OPENSSL" != yes ||
test "$CONFIG_OWN_LIBC" = yes;
then
AC_MSG_CHECKING(for built-in SHA1 support)
AC_MSG_RESULT(yes)
EL_CONFIG(CONFIG_SHA1, [Built-in SHA1])
fi
fi
AC_SUBST(CONFIG_SHA1)
if test "$CONFIG_CSS" = yes || test "$CONFIG_DOM" = yes;
then
EL_CONFIG(CONFIG_SCANNER, [Built-in scanner])
fi
AC_SUBST(CONFIG_SCANNER)
AC_ARG_ENABLE(weehoofooboomookerchoo,
[
Also check out the features.conf file for more information about features!
@ -1347,10 +1388,13 @@ AC_OUTPUT([ \
abs_srcdir="$(cd "$srcdir" && pwd)"
# builddir is always absolute!
if test "$abs_srcdir" != "$builddir"; then
# Bootstrap the Makefile creation
echo "include $abs_srcdir/Makefile" > "$builddir/Makefile"
"$MAKE" "SRC=$abs_srcdir" init
fi
# Make cg-status ignore this build directory
echo "*" > "$builddir/.gitignore"
fi
dnl ===================================================================
dnl Configuration summary

View File

@ -1,2 +0,0 @@
fspcgi: fspcgi.o
$(CC) -o $@ $< -lfsplib

View File

@ -1,8 +0,0 @@
To use this CGI script you need to build fspcgi and copy the executable
to your cgi directory. In ELinks, you can then use this URL:
file:///"path_to_fspcgi"?host:port/path_to_file_or_directory
You can find more info about the FSP protocol at
http://fsp.sourceforge.net/

View File

@ -1,172 +0,0 @@
/* CGI script for FSP protocol support */
#include <ctype.h>
#include <fsplib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
char *pname, *query;
struct fq {
char *password;
char *host;
char *path;
unsigned short port;
} data;
static void
error(const char *str)
{
printf("Content-Type: text/plain\r\nConnection: close\r\n\r\n");
puts(str);
printf("%s\n", query);
exit(1);
}
static void
process_directory(FSP_SESSION *ses)
{
char buf[1024];
FSP_DIR *dir;
/* TODO: password */
snprintf(buf, sizeof(buf), "file://%s?%s:%d%s/", pname, data.host,
data.port, data.path);
printf("Content-Type: text/html\r\n\r\n");
printf("<html><head><title>%s</title></head><body>\n", buf);
dir = fsp_opendir(ses, data.path);
if (dir) {
FSP_RDENTRY fentry, *fresult;
while (!fsp_readdir_native(dir, &fentry, &fresult)) {
if (!fresult) break;
printf("<a href=\"%s%s\">%s</a><br>\n", buf, fentry.name, fentry.name);
}
fsp_closedir(dir);
}
puts("</body></html>");
fsp_close_session(ses);
exit(0);
}
static void
process_data(void)
{
FSP_SESSION *ses = fsp_open_session(data.host, data.port, data.password);
struct stat sb;
if (!ses) error("Session initialization failed.");
if (fsp_stat(ses, data.path, &sb)) error("File not found.");
if (S_ISDIR(sb.st_mode)) process_directory(ses);
else { /* regular file */
char buf[4096];
FSP_FILE *file = fsp_fopen(ses, data.path, "r");
int r;
if (!file) error("fsp_fopen error.");
printf("Content-Type: application/octet-stream\r\nContent-Length: %d\r\n"
"Connection: close\r\n\r\n", sb.st_size);
while ((r = fsp_fread(buf, 1, 4096, file)) > 0) fwrite(buf, 1, r, stdout);
fsp_fclose(file);
fsp_close_session(ses);
exit(0);
}
}
static void
process_query(void)
{
char *at = strchr(query, '@');
char *colon;
char *slash;
if (at) {
*at = '\0';
data.password = strdup(query);
query = at + 1;
}
colon = strchr(query, ':');
if (colon) {
*colon = '\0';
data.host = strdup(query);
data.port = atoi(colon + 1);
slash = strchr(colon + 1, '/');
if (slash) {
data.path = strdup(slash);
} else {
data.path = "/";
}
} else {
data.port = 21;
slash = strchr(query, '/');
if (slash) {
*slash = '\0';
data.host = strdup(query);
*slash = '/';
data.path = strdup(slash);
} else {
data.host = strdup(query);
data.path = "/";
}
}
process_data();
}
static inline int
unhx(register unsigned char a)
{
if (isdigit(a)) return a - '0';
if (a >= 'a' && a <= 'f') return a - 'a' + 10;
if (a >= 'A' && a <= 'F') return a - 'A' + 10;
return -1;
}
static void
decode_query(char *src)
{
char *dst = src;
char c;
do {
c = *src++;
if (c == '%') {
int x1 = unhx(*src);
if (x1 >= 0) {
int x2 = unhx(*(src + 1));
if (x2 >= 0) {
x1 = (x1 << 4) + x2;
if (x1 != 0) { /* don't allow %00 */
c = (unsigned char) x1;
src += 2;
}
}
}
} else if (c == '+') {
c = ' ';
}
*dst++ = c;
} while (c != '\0');
}
int
main(int argc, char **argv)
{
char *q = getenv("QUERY_STRING");
if (!q) return 1;
pname = argv[0];
query = strdup(q);
if (!query) return 2;
decode_query(query);
process_query();
return 0;
}

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,10 +1,41 @@
def goto_url_hook(url):
return None
import re
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
def pre_format_html_hook(url, html):
if re.search("cygwin\.com", url):
html2 = re.sub("<body bgcolor=\"#000000\" color=\"#000000\"", "<body bgcolor=\"#ffffff\" color=\"#000000\"", html)
return html2
return None
def proxy_for_hook(url):

View File

@ -0,0 +1,17 @@
/* Play videos at video.google.com with minimal niggling. Just follow the link
* from the front page or the search page, and the video will automatically
* be loaded. */
function load_google_video(cached, vs) {
if (!cached.uri.match(/^http:\/\/video.google.com\/videoplay/))
return true;
var re = /(<object data="\/googleplayer.swf\?videoUrl=)(.*?)(\&.*?<\/object>)/;
var match = cached.content.match(re);
var url = unescape(match[2]);
var meta = '<meta http-equiv="refresh" content="1; url=' + url + '" />';
cached.content = cached.content.replace(/<head>/, "<head>" + meta);
return true;
}
elinks.preformat_html_hooks.push(load_google_video);

View File

@ -8,9 +8,9 @@ elinks.keymaps.main["@"] = function () {
};
elinks.preformat_html_hooks = new Array();
elinks.preformat_html = function (cached) {
elinks.preformat_html = function (cached, vs) {
for (var i in elinks.preformat_html_hooks)
if (!elinks.preformat_html_hooks[i](cached))
if (!elinks.preformat_html_hooks[i](cached, vs))
return false;
return true;
@ -36,13 +36,13 @@ elinks.follow_url_hook = function (url) {
return url;
};
function root_w00t(cached) {
function root_w00t(cached, vs) {
cached.content = cached.content.replace(/root/g, "w00t");
return true;
};
elinks.preformat_html_hooks.push(root_w00t);
function mangle_deb_bugnumbers(cached) {
function mangle_deb_bugnumbers(cached, vs) {
if (!cached.uri.match(/^[a-z0-9]+:\/\/[a-z0-9A-Z.-]+debian\.org/)
&& !cached.uri.match(/changelog\.Debian/))
return true;
@ -55,7 +55,14 @@ function mangle_deb_bugnumbers(cached) {
/* Debian Policy Manual 4.4 footnote 16 */
var closes_re = /closes:\s*(?:bug)?\#?\s?\d+(?:,\s*(?:bug)?\#?\s?\d+)*/gi;
cached.content = cached.content.replace(closes_re, rewrite_closes_fn);
var new_content = cached.content.replace(closes_re, rewrite_closes_fn);
if (cached.type == 'text/plain') {
cached.content = '<pre>' + new_content + '</pre>';
vs.plain = "0";
} else {
cached.content = new_content;
}
return true;
}

View File

@ -58,7 +58,7 @@ function cvsweb (base, project, url)
/* javascript:gitweb("http://pasky.or.cz/gitweb.cgi", "elinks.git", "%s"); */
function gitweb(base, project, url)
{
var parts = url.match(/^(search|summary|shortlog|log|commit|commitdiff|tree|tag)(\s(.*))?/);
var parts = url.match(/^(search|summary|shortlog|log|blob|commit|commitdiff|history|tree|tag)(\s(.*))?/);
var query = '?p=' + project;
if (parts) {
@ -67,6 +67,8 @@ function gitweb(base, project, url)
/* If the extra arg is not for searching assume it is an ID. */
if (parts[1] == 'search' && parts[3])
query += ';s=' + escape(parts[3]);
else if ((parts[1] == 'blob' || parts[1] == 'history' || parts[1] == 'tree') && parts[3])
query += ';f=' + escape(parts[3]);
else if (parts[3])
query += ';h=' + escape(parts[3]);

15
contrib/vim/c_elinks.vim Normal file
View File

@ -0,0 +1,15 @@
" Setting Vim to support the ELinks coding style
"
" To use this file, drop it in ~/.vim/ftplugin and set filetype plugin on.
" Finally, make sure the path to the source directory contains the word
" 'elinks', for example ~/src/elinks/.
"
" For .h files, link it as cpp_elinks.vim or define c_syntax_for_h in ~/.vimrc.
" For .inc files, let g:filetype_inc = 'c' in ~/.vimrc.
if expand('%:p:h') =~ '.*elinks.*'
setlocal shiftwidth=8
setlocal tabstop=8
setlocal softtabstop=0
setlocal noexpandtab
endif

2
debian/.vimrc vendored
View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../.vimrc

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../.vimrc

View File

@ -12,6 +12,9 @@ docdir = $(datadir)/doc
HTML_DIR = $(DESTDIR)$(docdir)/$(PACKAGE)/html
PDF_DIR = $(DESTDIR)$(docdir)/$(PACKAGE)/pdf
ASCIIDOC_CONF = $(srcdir)asciidoc.conf
ASCIIDOC_FLAGS += -f $(ASCIIDOC_CONF) -a "builddir=$(CURDIR)/"
#############################################################################
# Build files
@ -108,11 +111,14 @@ quiet_cmd_help2doc = ' [$(LINK_COLOR)HELP2DOC$(END_COLOR)] $(RELPATH)$@'
cmd_help2doc = $(LOCALES) $(HELP2DOC) $(ELINKS) $@ > $@
quiet_cmd_conf2doc = ' [$(LINK_COLOR)CONF2DOC$(END_COLOR)] $(RELPATH)$@'
cmd_conf2doc = $(LOCALES) $(CONF2DOC) > $@
cmd_conf2doc = $(LOCALES) $(CONF2DOC) $(FEATURES) > $@
quiet_cmd_keys2doc = ' [$(LINK_COLOR)KEYS2DOC$(END_COLOR)] $(RELPATH)$@'
cmd_keys2doc = $(LOCALES) $(KEYS2DOC) $(KBDBIND) $@ > $@
quiet_cmd_code2doc = ' [$(LINK_COLOR)CODE2DOC$(END_COLOR)] $(RELPATH)$@'
cmd_code2doc = $(LOCALES) $(CODE2DOC) $< > $@
features.txt: $(FEATURES) $(CONF2DOC)
$(call cmd,conf2doc)
@ -130,10 +136,10 @@ API = $(shell find $(top_srcdir)/src/ -name '*.h' -exec grep -q 'API Doc' \{\} \
endif
define api_doc
API_TXT += api/$(2).txt
api/$(2).txt: $(1) $(CODE2DOC)
@test -d api || $(MKINSTALLDIRS) api
@$(CODE2DOC) $(1) > $$@
API_TXT += api/$(2).txt
$$(call cmd,code2doc)
endef
api_name = $(shell sed -n 's/.*API Doc\s*::\s*\([^ ]*\).*/\1/p' < $(1))
@ -149,25 +155,27 @@ api: $(patsubst %.txt,%.html,$(API_TXT))
cmd_jw = $(JW) -b $(2) $<
quiet_cmd_xmlto = ' [$(LINK_COLOR)XMLTO$(END_COLOR)] $(RELPATH)$@'
cmd_xmlto = $(XMLTO) $(3) $(2) $<
cmd_xmlto = $(XMLTO) -o $(call outdir) $(3) $(2) $<
quiet_cmd_pod2html = ' [$(LINK_COLOR)POD2HTML$(END_COLOR)] $(RELPATH)$@'
cmd_pod2html = $(POD2HTML) --outfile=$@ < $<
quiet_cmd_asciidoc = ' [$(LINK_COLOR)ASCIIDOC$(END_COLOR)] $(RELPATH)$@'
cmd_asciidoc = $(ASCIIDOC) -f asciidoc.conf -b $(2) -d $(call doctype,$<) -o $@ $<
cmd_asciidoc = $(ASCIIDOC) $(ASCIIDOC_FLAGS) -b $(call backend) -d $(call doctype) -o $@ $<
# Based on filename in $(1) find out asciidoc doctype.
doctype = $(if $(findstring .1.,$(1)),manpage,$(if $(findstring .5.,$(1)),manpage,book))
# Based on $@ find out asciidoc doctype or backend + xmlto output dir.
doctype = $(if $(findstring .1.,$@)$(findstring .5.,$@),manpage,book)
backend = $(if $(findstring .xml,$@),docbook,xhtml11)
outdir = $(if $(findstring -chunked,$@),$@,.)
# Loosely track dependencies via asciidoc includes.
asciidoc_dep = sed -n 's@include::\(.*\)\[.*@$@: \1@p' < $< > .deps/$(@F).asciidoc
asciidoc_dep = sed -n 's/[{]builddir}//g;s@include::\(.*\)\[.*@$@: $< \1@p' < $< > .deps/$(@F).asciidoc
-include .deps/*.asciidoc
# Do a little post-processing of man pages. Inserting title headers and date.
MAN_DATE = $(shell date -I)
man_desc = `sed -n 's/:Description:\s*\(.*\)/\1/p' < $(subst .xml,.txt,$<)`
man_desc = `sed -n 's/:Description:\s*\(.*\)/\1/p' < $(srcdir)$(subst .xml,.txt,$(<F))`
man_hack = sed "s/^\(\.TH \"ELINKS[^\"]*\" [0-9] \).*/\1\"$(1)\" \"$(MAN_DATE)\" \"$(1)\"/" < $@ | \
sed "s/@squote@/\\\\'/g" > $@.tmp && mv $@.tmp $@
@ -175,11 +183,11 @@ man_hack = sed "s/^\(\.TH \"ELINKS[^\"]*\" [0-9] \).*/\1\"$(1)\" \"$(MAN_DATE)\"
#############################################################################
# Build recipies
%.html: %.txt asciidoc.conf
%.html: %.txt $(ASCIIDOC_CONF)
$(call cmd,asciidoc,xhtml11)
@-$(call asciidoc_dep)
%.xml: %.txt asciidoc.conf
%.xml: %.txt $(ASCIIDOC_CONF)
$(call cmd,asciidoc,docbook)
@-$(call asciidoc_dep)
@ -192,7 +200,7 @@ man_hack = sed "s/^\(\.TH \"ELINKS[^\"]*\" [0-9] \).*/\1\"$(1)\" \"$(MAN_DATE)\"
@$(call man_hack,$(call man_desc))
%.html-chunked: %.xml
$(call cmd,xmlto,html,-o $@)
$(call cmd,xmlto,html)
%.pdf: %.xml
$(call cmd,jw,pdf)

View File

@ -57,7 +57,8 @@ in this directory or it's children.
submitting patches etc., thus every aspiring developer should take the
pains to read through it, do not forget to also look for README and similar
text files in the subdirectories containing the relevant sources for
detailed notes regarding given modules/subsystems.
detailed notes regarding given modules/subsystems. Additionally, it is
possible to build API docs. More about this below.
The Lua Scripting Book ...................... lua-scripting.txt
Events Reference Sheet ...................... events.txt
@ -94,7 +95,10 @@ and the following man page formats:
- HTML (asciidoc)
- man / groff (asciidoc + xmlto)
Note: You do not need to build manpages. They are shipped with ELinks.
Note: You do not need to build manpages. They are shipped with ELinks. However,
if you want to have the manpages to match your local configuration and changes
you can rebuild them (this is mostly an issue with elinks.conf(5) which might
otherwise contain options that is not supported by the version you install.
Note: You must first build the ELinks binary for "make all-docs" to work
successfully. The binary is used for getting option documentation.
@ -103,6 +107,43 @@ The documentation can be installed with:
$ make install-doc
Building API documentation
^^^^^^^^^^^^^^^^^^^^^^^^^^
There is some starting effort to make it possible to build HTML documentation
of the APIs presented by the different modules and subsystems in ELinks. To
build API documentation run:
$ make api
in the doc/ directory. The API documentation can then be found in the doc/api/
directory.
NOTE: Currently only few files provides API docs and there is no over-all
structure of the various APIs.
The API toolchain uses a Perl script (doc/tools/code2doc) to extract info from
header files and generate text files with AsciiDoc markup. The text files are
then converted to HTML with AsciiDoc.
To get an idea of how the code markup works take a look at src/dom/stack.h.
It has a small tag saying that it provides API docs for the dom-stack module:
/* API Doc :: dom-stack */
The API doc markup should be pretty straight forward. Here is an example of the
basic structure:
/** <title>
*
* <content>
*/
Only text in comments starting with '/**' are used. If the comment immediately
preceeds a declaration of some struct, enum, typedef, function, or macro, the
name of the declared identifier will be used when creating the output to create
anchors which can be referred to using ref:[].
Contributing
------------

View File

@ -35,7 +35,7 @@ Most options can be set in the user interface or config file, so usually you
do not need to care about them. Note that this list is roughly equivalent to
the output of running ELinks with the option `--long-help`.
include::option-command.txt[]
include::{builddir}option-command.txt[]
ENVIRONMENT VARIABLES
---------------------

View File

@ -56,7 +56,7 @@ Some sample settings:
OPTIONS
-------
include::option-config.txt[]
include::{builddir}option-config.txt[]
SEE ALSO
--------

View File

@ -93,7 +93,7 @@ FIXME:
KEYMAP ACTIONS
--------------
include::keymap-actions.txt[]
include::{builddir}keymap-actions.txt[]
DEFAULT BINDINGS
----------------
@ -101,7 +101,7 @@ DEFAULT BINDINGS
The default bindings are shown below. Any bindings in `~/.elinks/elinks.conf`
will override these.
include::keymap-defaults.txt[]
include::{builddir}keymap-defaults.txt[]
AUTHOR
------

View File

@ -71,6 +71,6 @@ include::small.txt[]
include::ecmascript.txt[]
include::features.txt[]
include::{builddir}features.txt[]
endif::installation-webpage[]

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../../.vimrc

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../../../.vimrc

View File

@ -17,7 +17,7 @@
.el .ne 3
.IP "\\$1" \\$2
..
.TH "ELINKS" 1 "The Elinks text-browser" "2006-01-14" "The Elinks text-browser"
.TH "ELINKS" 1 "The Elinks text-browser" "2006-01-31" "The Elinks text-browser"
.SH NAME
elinks \- lynx-like alternative character mode WWW browser
.SH "SYNOPSIS"
@ -279,7 +279,7 @@ History file containing most recently visited URLs\&.
GoTo URL dialog history file\&.
.TP
~/\&.elinks/hooks\&.{js,lua,pl,py,pl,scm}
~/\&.elinks/hooks\&.{js,lua,pl,py,rb,scm}
Browser scripting hooks\&.
.TP

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../../../.vimrc

View File

@ -17,7 +17,7 @@
.el .ne 3
.IP "\\$1" \\$2
..
.TH "ELINKS.CONF" 5 "ELinks configuration file" "2006-01-14" "ELinks configuration file"
.TH "ELINKS.CONF" 5 "ELinks configuration file" "2006-01-31" "ELinks configuration file"
.SH NAME
elinks.conf \- ELinks configuration file
.SH "SYNOPSIS"
@ -1156,6 +1156,18 @@ Allow blacklisting of buggy peers\&.
protocol\&.file
Options specific to local browsing\&.
.TP
protocol\&.file\&.allow_special_files [0|1] (default: 0)
Whether to allow reading from non\-regular files\&. Note this can be dangerous; reading /dev/urandom or /dev/zero can ruin your day!
.TP
protocol\&.file\&.show_hidden_files [0|1] (default: 1)
When set to false, files with name starting with a dot will be hidden in local directories listing\&.
.TP
protocol\&.file\&.try_encoding_extensions [0|1] (default: 1)
When set, if we can't open a file named 'filename', we'll try to open 'filename' with some encoding extension appended (ie\&. 'filename\&.gz'); it depends on the supported encodings\&.
.TP
protocol\&.file\&.cgi
Local CGI specific options\&.
@ -1169,16 +1181,12 @@ protocol\&.file\&.cgi\&.policy [0|1] (default: 0)
Whether to execute local CGI scripts\&.
.TP
protocol\&.file\&.allow_special_files [0|1] (default: 0)
Whether to allow reading from non\-regular files\&. Note this can be dangerous; reading /dev/urandom or /dev/zero can ruin your day!
protocol\&.fsp
FSP specific options\&.
.TP
protocol\&.file\&.show_hidden_files [0|1] (default: 1)
When set to false, files with name starting with a dot will be hidden in local directories listing\&.
.TP
protocol\&.file\&.try_encoding_extensions [0|1] (default: 1)
When set, if we can't open a file named 'filename', we'll try to open 'filename' with some encoding extension appended (ie\&. 'filename\&.gz'); it depends on the supported encodings\&.
protocol\&.fsp\&.sort [0|1] (default: 1)
Whether to sort entries in directory listings\&.
.TP
protocol\&.ftp

View File

@ -14,7 +14,7 @@ command-line arguments. The built-in documentation is sure to be up-to-date.
There was a complete (or, for the most part complete) manual for Links 0.82 at
one time, and you can still find it at:
http://links.sourceforge.net/docs/manual-0.82-en/index.html
- http://links.sourceforge.net/docs/manual-0.82-en/index.html[]
While large parts of it do not apply anymore, you may still find some relevant
information there.

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../../.vimrc

View File

@ -21,14 +21,12 @@ usage($HELP) if $opt_h or @ARGV < 1;
sub put_section {
if ($title) {
print "\n$title\n";
$_ = $title;
s/[^-]/-/g;
print "$_\n" if not $indent;
$title =~ s/[^-]/-/g;
print "$title\n" if not $indent;
}
if ($body) {
$_ = $body;
s/#newline#/$indent/g;
print "$_\n";
$body =~ s/#newline#/$indent/g;
print "$body\n";
}
$title = $body = undef;
}

View File

@ -4,6 +4,7 @@
# Copyright (c) Jonas Fonseca <fonseca@diku.dk>, 2005
#
CONFFILE="$1"
TMPFILE=$(mktemp import-features.conf.XXXXXX) || exit 1
strip_comment()
@ -53,7 +54,7 @@ __END__
fi
}
cat ../features.conf | while read line; do
cat "$CONFFILE" | while read line; do
case "$line" in
"### "*)
print_section

View File

@ -297,6 +297,21 @@ CONFIG_DATA=yes
CONFIG_FINGER=no
### File Service Protocol
#
# File Service Protocol (FSP) is a very lightweight UDP based protocol for
# transferring files. FSP has many benefits over FTP, mainly for running
# anonymous archives. FSP protocol is valuable in all kinds of environments
# because it is one of the only TCP/IP protocols that is not aggressive about
# bandwidth, while still being sufficiently fault tolerant.
#
# FSP is what anonymous FTP *should* be!
#
# See http://fsp.sourceforge.net/ for more info.
#
# Default: disabled
CONFIG_FSP=no
### File Transfer Protocol Support
#

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../.vimrc

238
po/fr.po
View File

@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: ELinks 0.12.GIT\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-01-10 23:00+0100\n"
"PO-Revision-Date: 2006-01-10 23:01+0100\n"
"POT-Creation-Date: 2006-01-30 23:26+0100\n"
"PO-Revision-Date: 2006-01-30 23:28+0100\n"
"Last-Translator: Laurent Monin <zas@norz.org>\n"
"Language-Team: French <zas@norz.org>\n"
"MIME-Version: 1.0\n"
@ -33,7 +33,7 @@ msgstr "Pressez espace pour d
#: src/bfu/msgbox.c:189 src/config/dialogs.c:57 src/config/dialogs.c:391
#: src/cookies/dialogs.c:354 src/dialogs/edit.c:97 src/dialogs/info.c:133
#: src/dialogs/options.c:210 src/dialogs/options.c:290 src/mime/dialogs.c:129
#: src/protocol/auth/dialogs.c:110 src/protocol/protocol.c:231
#: src/protocol/auth/dialogs.c:110 src/protocol/protocol.c:234
#: src/scripting/lua/core.c:377 src/scripting/lua/core.c:457
#: src/session/session.c:792 src/viewer/text/search.c:1593
msgid "~OK"
@ -187,7 +187,7 @@ msgid "Digital clock in the status bar."
msgstr "Horloge digitale dans la barre de status."
#: src/bfu/leds.c:77 src/bfu/leds.c:94 src/config/options.inc:1118
#: src/config/options.inc:1125 src/ecmascript/ecmascript.c:39
#: src/config/options.inc:1125 src/ecmascript/ecmascript.c:41
#: src/globhist/globhist.c:63 src/mime/backend/mailcap.c:93
#: src/mime/backend/mimetypes.c:52 src/network/ssl/ssl.c:80
msgid "Enable"
@ -1796,7 +1796,7 @@ msgid "Description"
msgstr "Description"
#: src/config/dialogs.c:320 src/protocol/bittorrent/dialogs.c:594
#: src/protocol/protocol.c:225 src/session/session.c:282
#: src/protocol/protocol.c:228 src/session/session.c:282
#: src/session/session.c:954 src/viewer/text/textarea.c:331
#: src/viewer/text/textarea.c:338
msgid "Error"
@ -3747,7 +3747,7 @@ msgstr "Texte"
msgid "Dialog text colors."
msgstr "Couleurs du texte des dialogues."
#: src/config/options.inc:978 src/viewer/text/form.c:1460
#: src/config/options.inc:978 src/viewer/text/form.c:1462
msgid "Checkbox"
msgstr "Case à cocher"
@ -3795,7 +3795,7 @@ msgstr "Raccourci du bouton"
msgid "Selected button shortcut"
msgstr "Raccourci du bouton sélectionné"
#: src/config/options.inc:1006 src/viewer/text/form.c:1464
#: src/config/options.inc:1006 src/viewer/text/form.c:1466
msgid "Text field"
msgstr "Champ texte"
@ -4400,7 +4400,7 @@ msgid "Domain"
msgstr "Domaine"
#: src/cookies/dialogs.c:37 src/mime/backend/mailcap.c:97
#: src/mime/backend/mimetypes.c:56 src/protocol/file/file.c:47
#: src/mime/backend/mimetypes.c:56 src/protocol/file/cgi.c:43
msgid "Path"
msgstr "Chemin"
@ -5358,31 +5358,31 @@ msgstr ""
"Laisser à \"\" pour utiliser le style initial du document."
#. name:
#: src/ecmascript/ecmascript.c:35 src/ecmascript/ecmascript.c:137
#: src/ecmascript/ecmascript.c:37 src/ecmascript/ecmascript.c:247
msgid "ECMAScript"
msgstr "ECMAScript"
#: src/ecmascript/ecmascript.c:37
#: src/ecmascript/ecmascript.c:39
msgid "ECMAScript options."
msgstr "Options d'ECMAScript."
#: src/ecmascript/ecmascript.c:41
#: src/ecmascript/ecmascript.c:43
msgid "Whether to run those scripts inside of documents."
msgstr "Exécuter ou non ces scripts présents dans les documents."
#: src/ecmascript/ecmascript.c:43
#: src/ecmascript/ecmascript.c:45
msgid "Script error reporting"
msgstr "Rapport d'erreur de script"
#: src/ecmascript/ecmascript.c:45
#: src/ecmascript/ecmascript.c:47
msgid "Open a message box when a script reports an error."
msgstr "Ouvrir une boîte de message quand un script produit une erreur."
#: src/ecmascript/ecmascript.c:47
#: src/ecmascript/ecmascript.c:49
msgid "Ignore <noscript> content"
msgstr "Ignorer le contenu de <noscript>"
#: src/ecmascript/ecmascript.c:49
#: src/ecmascript/ecmascript.c:51
msgid ""
"Whether to ignore content enclosed by the <noscript> tag\n"
"when ECMAScript is enabled."
@ -5390,29 +5390,29 @@ msgstr ""
"Ignorer ou non le contenu du tag <noscript> quand ECMAScript\n"
"est actif."
#: src/ecmascript/ecmascript.c:52
#: src/ecmascript/ecmascript.c:54
msgid "Maximum execution time"
msgstr "Temps maximal d'exécution"
#: src/ecmascript/ecmascript.c:54
#: src/ecmascript/ecmascript.c:56
msgid "Maximum execution time in seconds for a script."
msgstr "Temps maximal pour l'exécution d'un script, en secondes."
#: src/ecmascript/ecmascript.c:56
#: src/ecmascript/ecmascript.c:58
msgid "Pop-up window blocking"
msgstr "Blocage des fenêtres Javascript (popups)"
#: src/ecmascript/ecmascript.c:58
#: src/ecmascript/ecmascript.c:60
msgid "Whether to disallow scripts to open new windows or tabs."
msgstr ""
"Interdire ou non l'ouverture de fenêtres ou d'onglets\n"
"par les scripts."
#: src/ecmascript/ecmascript.c:126
#: src/ecmascript/ecmascript.c:226
msgid "JavaScript Emergency"
msgstr "Alerte JavaScript"
#: src/ecmascript/ecmascript.c:128
#: src/ecmascript/ecmascript.c:228
#, c-format
msgid ""
"A script embedded in the current document was running\n"
@ -5425,16 +5425,16 @@ msgstr ""
"qu'il y a un bogue dans ce script et que cela aurait pû\n"
"bloquer ELinks, l'exécution du script a donc été interrompue."
#: src/ecmascript/see/window.c:242 src/ecmascript/spidermonkey/window.c:286
#: src/ecmascript/see/window.c:216 src/ecmascript/spidermonkey/window.c:286
msgid "JavaScript Alert"
msgstr "Alerte JavaScript"
#: src/ecmascript/spidermonkey.c:162
#: src/ecmascript/spidermonkey.c:88
#, c-format
msgid "A script embedded in the current document raised the following%s%s%s%s"
msgstr "Un script contenu dans le document courant a provoqué%s%s%s%s"
#: src/ecmascript/spidermonkey.c:178
#: src/ecmascript/spidermonkey.c:104
msgid "JavaScript Error"
msgstr "Erreur Javascript"
@ -5784,7 +5784,7 @@ msgstr "Turque"
msgid "Ukrainian"
msgstr "Ukrainien"
#: src/main/interlink.c:325 src/main/select.c:255
#: src/main/interlink.c:329 src/main/select.c:255
#, c-format
msgid "The call to %s failed: %d (%s)"
msgstr "L'appel à %s a échoué: %d (%s)"
@ -7140,40 +7140,45 @@ msgstr "A~fficher"
msgid "Show ~header"
msgstr "~Montrer les en-têtes"
#: src/protocol/file/file.c:38
msgid "Local files"
msgstr "Fichiers locaux"
#: src/protocol/file/file.c:40
msgid "Options specific to local browsing."
msgstr "Options pour la navigation locale."
#: src/protocol/file/file.c:43
#: src/protocol/file/cgi.c:39
msgid "Local CGI"
msgstr "Scripts CGI locaux"
#: src/protocol/file/file.c:45
#: src/protocol/file/cgi.c:41
msgid "Local CGI specific options."
msgstr "Options des scripts CGI locaux."
#: src/protocol/file/file.c:49
#: src/protocol/file/cgi.c:45
msgid "Colon separated list of directories, where CGI scripts are stored."
msgstr ""
"Liste des répertoires où sont les scripts CGI (séparée par des virgules)."
#: src/protocol/file/file.c:51
#: src/protocol/file/cgi.c:47
msgid "Allow local CGI"
msgstr "Autoriser les scripts CGI locaux"
#: src/protocol/file/file.c:53
#: src/protocol/file/cgi.c:49
msgid "Whether to execute local CGI scripts."
msgstr "Exécuter ou non les scripts CGI locaux."
#: src/protocol/file/file.c:56
#. name:
#: src/protocol/file/cgi.c:54
msgid "CGI"
msgstr "CGI"
#: src/protocol/file/file.c:39
msgid "Local files"
msgstr "Fichiers locaux"
#: src/protocol/file/file.c:41
msgid "Options specific to local browsing."
msgstr "Options pour la navigation locale."
#: src/protocol/file/file.c:43
msgid "Allow reading special files"
msgstr "Autoriser la lecture des fichiers spéciaux"
#: src/protocol/file/file.c:58
#: src/protocol/file/file.c:45
msgid ""
"Whether to allow reading from non-regular files.\n"
"Note this can be dangerous; reading /dev/urandom or\n"
@ -7183,11 +7188,11 @@ msgstr ""
"Notez que cela peut être dangereux; lire /dev/urandom\n"
"ou /dev/zero peut ruiner votre journée !"
#: src/protocol/file/file.c:62
#: src/protocol/file/file.c:49
msgid "Show hidden files in directory listing"
msgstr "Montrer les fichiers cachés"
#: src/protocol/file/file.c:64
#: src/protocol/file/file.c:51
msgid ""
"When set to false, files with name starting with a dot will be\n"
"hidden in local directories listing."
@ -7196,11 +7201,11 @@ msgstr ""
"seront cachés lors de la visualisation du contenu d'un répertoire\n"
"local."
#: src/protocol/file/file.c:67
#: src/protocol/file/file.c:54
msgid "Try encoding extensions"
msgstr "Deviner l'extension des fichiers encodés"
#: src/protocol/file/file.c:69
#: src/protocol/file/file.c:56
msgid ""
"When set, if we can't open a file named 'filename', we'll try\n"
"to open 'filename' with some encoding extension appended\n"
@ -7211,7 +7216,7 @@ msgstr ""
"'un_nom.gz'); cela dépend des encodages supportés."
#. name:
#: src/protocol/file/file.c:77
#: src/protocol/file/file.c:64
msgid "File"
msgstr "File"
@ -7221,29 +7226,46 @@ msgid "Finger"
msgstr "Finger"
#. name:
#: src/protocol/ftp/ftp.c:55 src/protocol/ftp/ftp.c:85
#: src/protocol/fsp/fsp.c:44 src/protocol/fsp/fsp.c:56
msgid "FSP"
msgstr "FSP"
#: src/protocol/fsp/fsp.c:46
msgid "FSP specific options."
msgstr "Options du protocole FSP."
#: src/protocol/fsp/fsp.c:48
msgid "Sort entries"
msgstr "Trier les entrées"
#: src/protocol/fsp/fsp.c:50
msgid "Whether to sort entries in directory listings."
msgstr "Trier ou non les entrées des répertoires."
#. name:
#: src/protocol/ftp/ftp.c:56 src/protocol/ftp/ftp.c:86
msgid "FTP"
msgstr "FTP"
#: src/protocol/ftp/ftp.c:57
#: src/protocol/ftp/ftp.c:58
msgid "FTP specific options."
msgstr "Options du protocole FTP."
#: src/protocol/ftp/ftp.c:59 src/protocol/http/http.c:124
#: src/protocol/ftp/ftp.c:60 src/protocol/http/http.c:124
#: src/protocol/http/http.c:206
msgid "Proxy configuration"
msgstr "Configuration proxy"
#: src/protocol/ftp/ftp.c:61
#: src/protocol/ftp/ftp.c:62
msgid "FTP proxy configuration."
msgstr "Configuration proxy FTP."
#: src/protocol/ftp/ftp.c:63 src/protocol/http/http.c:128
#: src/protocol/ftp/ftp.c:64 src/protocol/http/http.c:128
#: src/protocol/http/http.c:210
msgid "Host and port-number"
msgstr "Hôte et numéro de port"
#: src/protocol/ftp/ftp.c:65
#: src/protocol/ftp/ftp.c:66
msgid ""
"Host and port-number (host:port) of the FTP proxy, or blank.\n"
"If it's blank, FTP_PROXY environment variable is checked as well."
@ -7251,36 +7273,36 @@ msgstr ""
"Hôte et numéro de port (hôte:port) du proxy FTP, ou rien.\n"
"Si rien, la variable d'environnement FTP_PROXY sera utilisée."
#: src/protocol/ftp/ftp.c:68
#: src/protocol/ftp/ftp.c:69
msgid "Anonymous password"
msgstr "Mot de passe anonyme"
#: src/protocol/ftp/ftp.c:70
#: src/protocol/ftp/ftp.c:71
msgid "FTP anonymous password to be sent."
msgstr "Mot de passe pour l'accès FTP anonyme."
#: src/protocol/ftp/ftp.c:72
#: src/protocol/ftp/ftp.c:73
msgid "Use passive mode (IPv4)"
msgstr "Utiliser le mode passif (IPv4)"
#: src/protocol/ftp/ftp.c:74
#: src/protocol/ftp/ftp.c:75
msgid "Use PASV instead of PORT (passive vs active mode, IPv4 only)."
msgstr ""
"Utiliser PASV au lieu de PORT (mode passif contre mode actif, IPv4\n"
"seulement)."
#: src/protocol/ftp/ftp.c:76
#: src/protocol/ftp/ftp.c:77
msgid "Use passive mode (IPv6)"
msgstr "Utiliser le mode passif (IPv6)"
#: src/protocol/ftp/ftp.c:78
#: src/protocol/ftp/ftp.c:79
msgid "Use EPSV instead of EPRT (passive vs active mode, IPv6 only)."
msgstr ""
"Utiliser EPSV au lieu de EPRT (mode passif contre mode actif, IPv6\n"
"seulement)."
#. name:
#: src/protocol/gopher/gopher.c:46
#: src/protocol/gopher/gopher.c:47
msgid "Gopher"
msgstr "Gopher"
@ -7573,25 +7595,25 @@ msgstr ""
"Toutes les entrées possibles peuvent être lues dans le dialogue\n"
"Info. En-têtes."
#: src/protocol/protocol.c:227
#: src/protocol/protocol.c:230
#, c-format
msgid "This version of ELinks does not contain %s protocol support"
msgstr ""
"Cette version de ELinks ne contient pas le support pour le protocole %s"
#: src/protocol/protocol.c:258
#: src/protocol/protocol.c:261
msgid "Protocols"
msgstr "Protocoles"
#: src/protocol/protocol.c:260
#: src/protocol/protocol.c:263
msgid "Protocol specific options."
msgstr "Options des protocoles."
#: src/protocol/protocol.c:262
#: src/protocol/protocol.c:265
msgid "No-proxy domains"
msgstr "Domaines ignorés en ce qui concerne les proxys"
#: src/protocol/protocol.c:264
#: src/protocol/protocol.c:267
msgid ""
"Comma separated list of domains for which the proxy (HTTP/FTP)\n"
"should be disabled. Optionally, a port can be specified for some\n"
@ -7604,7 +7626,7 @@ msgstr ""
"NO_PROXY sera utilisé."
#. name:
#: src/protocol/protocol.c:300
#: src/protocol/protocol.c:309
msgid "Protocol"
msgstr "Protocole"
@ -7731,19 +7753,19 @@ msgid "URI rewrite"
msgstr "Ré-écriture d'URI"
#. name:
#: src/protocol/smb/smb.c:72 src/protocol/smb/smb.c:84
#: src/protocol/smb/smb.c:67 src/protocol/smb/smb.c:79
msgid "SMB"
msgstr "SMB"
#: src/protocol/smb/smb.c:74
#: src/protocol/smb/smb.c:69
msgid "SAMBA specific options."
msgstr "Options spécifiques de SAMBA."
#: src/protocol/smb/smb.c:76
#: src/protocol/smb/smb.c:71
msgid "Credentials"
msgstr "Authentification"
#: src/protocol/smb/smb.c:78
#: src/protocol/smb/smb.c:73
msgid "Credentials file passed to smbclient via -A option."
msgstr "Fichier d'authentification passé à smbclient via l'option -A."
@ -8092,167 +8114,167 @@ msgstr "Erreur lors de l'envoi du formulaire"
msgid "Could not load file %s: %s"
msgstr "Impossible de charger le fichier %s: %s"
#: src/viewer/text/form.c:1445
#: src/viewer/text/form.c:1447
msgid "Reset form"
msgstr "Réinitialiser le formulaire"
#: src/viewer/text/form.c:1447
#: src/viewer/text/form.c:1449
msgid "Harmless button"
msgstr "Bouton sans impact"
#: src/viewer/text/form.c:1455
#: src/viewer/text/form.c:1457
msgid "Submit form to"
msgstr "Envoi du formulaire à"
#: src/viewer/text/form.c:1456
#: src/viewer/text/form.c:1458
msgid "Post form to"
msgstr "Transfert du formulaire à"
#: src/viewer/text/form.c:1458
#: src/viewer/text/form.c:1460
msgid "Radio button"
msgstr "Bouton radio"
#: src/viewer/text/form.c:1462
#: src/viewer/text/form.c:1464
msgid "Select field"
msgstr "Liste"
#: src/viewer/text/form.c:1466
#: src/viewer/text/form.c:1468
msgid "Text area"
msgstr "Champ texte multiligne"
#: src/viewer/text/form.c:1468
#: src/viewer/text/form.c:1470
msgid "File upload"
msgstr "Envoi de fichier"
#: src/viewer/text/form.c:1470
#: src/viewer/text/form.c:1472
msgid "Password field"
msgstr "Champ mot de passe"
#: src/viewer/text/form.c:1508
#: src/viewer/text/form.c:1510
msgid "name"
msgstr "Nom"
#: src/viewer/text/form.c:1520
#: src/viewer/text/form.c:1522
msgid "value"
msgstr "Valeur"
#: src/viewer/text/form.c:1533
#: src/viewer/text/form.c:1535
msgid "read only"
msgstr "lecture seule"
#: src/viewer/text/form.c:1544
#: src/viewer/text/form.c:1546
#, c-format
msgid "press %s to navigate"
msgstr "pressez %s pour naviguer"
#: src/viewer/text/form.c:1546
#: src/viewer/text/form.c:1548
#, c-format
msgid "press %s to edit"
msgstr "pressez %s pour éditer"
#: src/viewer/text/form.c:1582
#: src/viewer/text/form.c:1584
#, c-format
msgid "press %s to submit to %s"
msgstr "pressez %s pour soumettre à %s"
#: src/viewer/text/form.c:1584
#: src/viewer/text/form.c:1586
#, c-format
msgid "press %s to post to %s"
msgstr "pressez %s pour poster à %s"
#: src/viewer/text/form.c:1686
#: src/viewer/text/form.c:1688
msgid "Useless button"
msgstr "Bouton inutile"
#: src/viewer/text/form.c:1688
#: src/viewer/text/form.c:1690
msgid "Submit button"
msgstr "Bouton Soumettre"
#: src/viewer/text/link.c:1166
#: src/viewer/text/link.c:1209
msgid "Display ~usemap"
msgstr "Afficher ~usemap"
#: src/viewer/text/link.c:1169
#: src/viewer/text/link.c:1212
msgid "~Follow link"
msgstr "~Suivre le lien"
#: src/viewer/text/link.c:1171
#: src/viewer/text/link.c:1214
msgid "Follow link and r~eload"
msgstr "Suivre le lien et ~recharger"
#: src/viewer/text/link.c:1175
#: src/viewer/text/link.c:1218
msgid "Open in new ~window"
msgstr "Ouvrir dans une nouvelle ~fenêtre"
#: src/viewer/text/link.c:1177
#: src/viewer/text/link.c:1220
msgid "Open in new ~tab"
msgstr "Ouvrir dans un nouvel ongle~t"
#: src/viewer/text/link.c:1179
#: src/viewer/text/link.c:1222
msgid "Open in new tab in ~background"
msgstr "Ouvrir dans un nouvel onglet en arrière-~plan"
#: src/viewer/text/link.c:1184
#: src/viewer/text/link.c:1227
msgid "~Download link"
msgstr "~Enregistrer le lien"
#: src/viewer/text/link.c:1187
#: src/viewer/text/link.c:1230
msgid "~Add link to bookmarks"
msgstr "~Ajouter ce lien aux signets"
#: src/viewer/text/link.c:1199 src/viewer/text/link.c:1235
#: src/viewer/text/link.c:1242 src/viewer/text/link.c:1278
msgid "~Reset form"
msgstr "Remettre à ~zéro le formulaire"
#: src/viewer/text/link.c:1212
#: src/viewer/text/link.c:1255
msgid "Open in ~external editor"
msgstr "Ouvrir dans un ~éditeur externe"
#: src/viewer/text/link.c:1218
#: src/viewer/text/link.c:1261
msgid "~Submit form"
msgstr "~Envoyer le formulaire"
#: src/viewer/text/link.c:1219
#: src/viewer/text/link.c:1262
msgid "Submit form and rel~oad"
msgstr "Envoyer le formulaire et ~recharger"
#: src/viewer/text/link.c:1223
#: src/viewer/text/link.c:1266
msgid "Submit form and open in new ~window"
msgstr "Envoyer le formulaire et ouvrir dans une nouvelle ~fenêtre"
#: src/viewer/text/link.c:1225
#: src/viewer/text/link.c:1268
msgid "Submit form and open in new ~tab"
msgstr "Envoyer le formulaire et ouvrir un ~onglet"
#: src/viewer/text/link.c:1228
#: src/viewer/text/link.c:1271
msgid "Submit form and open in new tab in ~background"
msgstr "Envoyer le formulaire et ouvrir un onglet en ~arrière-plan"
#: src/viewer/text/link.c:1233
#: src/viewer/text/link.c:1276
msgid "Submit form and ~download"
msgstr "Envoyer le formulaire et ~télécharger"
#: src/viewer/text/link.c:1238
#: src/viewer/text/link.c:1281
msgid "Form f~ields"
msgstr "Champs de formula~ire"
#: src/viewer/text/link.c:1243
#: src/viewer/text/link.c:1286
msgid "V~iew image"
msgstr "~Voir l'image"
#: src/viewer/text/link.c:1245
#: src/viewer/text/link.c:1288
msgid "Download ima~ge"
msgstr "Enregistrer l'~image"
#: src/viewer/text/link.c:1253
#: src/viewer/text/link.c:1296
msgid "No link selected"
msgstr "Aucun lien sélectionné"
#: src/viewer/text/link.c:1301
#: src/viewer/text/link.c:1344
msgid "Image"
msgstr "Image"
#: src/viewer/text/link.c:1306
#: src/viewer/text/link.c:1349
msgid "Usemap"
msgstr "Usemap"

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

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../.vimrc

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../../.vimrc

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../../.vimrc

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../../../.vimrc

View File

@ -386,7 +386,7 @@ xbeltree_to_bookmarks_list(struct tree_node *node,
tmp = add_bookmark(current_parent, 0,
/* The <title> element is optional */
title ? title->text
title && title->text ? title->text
: (unsigned char *) gettext("No title"),
/* XXX: The href attribute isn't optional but
* we don't validate the source XML yet, so
@ -407,7 +407,7 @@ xbeltree_to_bookmarks_list(struct tree_node *node,
title = get_child(node, "title");
tmp = add_bookmark(current_parent, 0,
title ? title->text
title && title->text ? title->text
: (unsigned char *) gettext("No title"),
NULL);

2
src/cache/.vimrc vendored
View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../../.vimrc

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../../.vimrc

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../../.vimrc

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../../.vimrc

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../../.vimrc

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../../../.vimrc

View File

@ -11,6 +11,7 @@
struct cache_entry;
struct document_refresh;
struct document_view;
struct form_control;
struct frame_desc;
struct frameset_desc;
@ -147,6 +148,8 @@ struct document {
* dependencies between the various entries so nothing gets removed
* unneeded. */
struct uri_list ecmascript_imports;
/* For ecmascript access */
struct document_view *doc_view;
#endif
#ifdef CONFIG_CSS
/* FIXME: We should externally maybe using cache_entry store the
@ -185,6 +188,7 @@ struct document {
color_T bgcolor;
enum cp_status cp_status;
unsigned int links_sorted:1; /* whether links are already sorted */
};
#define document_has_frames(document_) ((document_) && (document_)->frame_desc)

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../../../.vimrc

View File

@ -22,8 +22,10 @@
#include "document/document.h"
#include "document/dom/renderer.h"
#include "document/renderer.h"
#include "dom/configuration.h"
#include "dom/scanner.h"
#include "dom/sgml/parser.h"
#include "dom/sgml/html/html.h"
#include "dom/sgml/rss/rss.h"
#include "dom/node.h"
#include "dom/stack.h"
@ -39,11 +41,14 @@
struct dom_renderer {
enum sgml_document_type doctype;
struct document *document;
struct conv_table *convert_table;
enum convert_string_mode convert_mode;
struct uri *base_uri;
unsigned char *source;
unsigned char *end;
@ -108,6 +113,7 @@ init_dom_renderer(struct dom_renderer *renderer, struct document *document,
renderer->source = buffer->source;
renderer->end = buffer->source + buffer->length;
renderer->position = renderer->source;
renderer->base_uri = get_uri_reference(document->uri);
#ifdef HAVE_REGEX_H
if (renderer->document->options.plain_display_links) {
@ -367,7 +373,7 @@ add_dom_link(struct dom_renderer *renderer, unsigned char *string, int length,
CSM_DEFAULT, NULL, NULL, NULL);
if (!uristring) return NULL;
where = join_urls(document->uri, uristring);
where = join_urls(renderer->base_uri, uristring);
mem_free(uristring);
@ -402,6 +408,7 @@ add_dom_link(struct dom_renderer *renderer, unsigned char *string, int length,
}
document->nlinks++;
document->links_sorted = 0;
return link;
}
@ -500,7 +507,7 @@ render_dom_node_enhanced_text(struct dom_renderer *renderer, struct dom_node *no
}
#endif
static void
static enum dom_code
render_dom_node_source(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_renderer *renderer = stack->current->data;
@ -513,15 +520,15 @@ render_dom_node_source(struct dom_stack *stack, struct dom_node *node, void *dat
|| node->type == DOM_NODE_CDATA_SECTION
|| node->type == DOM_NODE_COMMENT)) {
render_dom_node_enhanced_text(renderer, node);
return;
}
} else
#endif
render_dom_node_text(renderer, &renderer->styles[node->type], node);
render_dom_node_text(renderer, &renderer->styles[node->type], node);
return DOM_CODE_OK;
}
/* This callback is also used for rendering processing instruction nodes. */
static void
static enum dom_code
render_dom_element_source(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_renderer *renderer = stack->current->data;
@ -529,9 +536,11 @@ render_dom_element_source(struct dom_stack *stack, struct dom_node *node, void *
assert(node && renderer && renderer->document);
render_dom_node_text(renderer, &renderer->styles[node->type], node);
return DOM_CODE_OK;
}
static void
enum dom_code
render_dom_element_end_source(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_renderer *renderer = stack->current->data;
@ -544,7 +553,7 @@ render_dom_element_end_source(struct dom_stack *stack, struct dom_node *node, vo
assert(node && renderer && renderer->document);
if (!string || !length)
return;
return DOM_CODE_OK;
if (check_dom_node_source(renderer, string, length)) {
render_dom_flush(renderer, string);
@ -553,9 +562,32 @@ render_dom_element_end_source(struct dom_stack *stack, struct dom_node *node, vo
}
render_dom_text(renderer, &renderer->styles[node->type], string, length);
return DOM_CODE_OK;
}
static void
set_base_uri(struct dom_renderer *renderer, unsigned char *value, size_t valuelen)
{
unsigned char *href = memacpy(value, valuelen);
unsigned char *uristring;
struct uri *uri;
if (!href) return;
uristring = join_urls(renderer->base_uri, href);
mem_free(href);
if (!uristring) return;
uri = get_uri(uristring, 0);
mem_free(uristring);
if (!uri) return;
done_uri(renderer->base_uri);
renderer->base_uri = uri;
}
enum dom_code
render_dom_attribute_source(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_renderer *renderer = stack->current->data;
@ -609,6 +641,12 @@ render_dom_attribute_source(struct dom_stack *stack, struct dom_node *node, void
break;
}
if (renderer->doctype == SGML_DOCTYPE_HTML
&& node->data.attribute.type == HTML_ATTRIBUTE_HREF
&& node->parent->data.element.type == HTML_ELEMENT_BASE) {
set_base_uri(renderer, value, valuelen - skips);
}
add_dom_link(renderer, value, valuelen - skips,
value, valuelen - skips);
@ -620,9 +658,11 @@ render_dom_attribute_source(struct dom_stack *stack, struct dom_node *node, void
render_dom_text(renderer, template, value, valuelen);
}
}
return DOM_CODE_OK;
}
static void
enum dom_code
render_dom_cdata_source(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_renderer *renderer = stack->current->data;
@ -639,9 +679,11 @@ render_dom_cdata_source(struct dom_stack *stack, struct dom_node *node, void *da
}
render_dom_node_text(renderer, &renderer->styles[node->type], node);
return DOM_CODE_OK;
}
static void
enum dom_code
render_dom_document_end(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_renderer *renderer = stack->current->data;
@ -652,6 +694,8 @@ render_dom_document_end(struct dom_stack *stack, struct dom_node *node, void *da
if (check_dom_node_source(renderer, renderer->position, 0)) {
render_dom_flush(renderer, renderer->end);
}
return DOM_CODE_OK;
}
static struct dom_stack_context_info dom_source_renderer_context_info = {
@ -693,7 +737,10 @@ static struct dom_stack_context_info dom_source_renderer_context_info = {
/* DOM RSS Renderer */
static void
#define RSS_CONFIG_FLAGS \
(DOM_CONFIG_NORMALIZE_WHITESPACE | DOM_CONFIG_NORMALIZE_CHARACTERS)
enum dom_code
dom_rss_push_element(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_renderer *renderer = stack->current->data;
@ -735,9 +782,11 @@ dom_rss_push_element(struct dom_stack *stack, struct dom_node *node, void *data)
renderer->node = node;
}
return DOM_CODE_OK;
}
static void
enum dom_code
dom_rss_pop_element(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_renderer *renderer = stack->current->data;
@ -776,74 +825,21 @@ dom_rss_pop_element(struct dom_stack *stack, struct dom_node *node, void *data)
default:
break;
}
}
static void
dom_rss_push_content(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_renderer *renderer = stack->current->data;
unsigned char *string = node->string.string;
int length = node->string.length;
assert(node && renderer && renderer->document);
if (!renderer->node)
return;
if (node->type == DOM_NODE_ENTITY_REFERENCE) {
string -= 1;
length += 2;
}
if (!is_dom_string_set(&renderer->text)) {
init_dom_string(&renderer->text, string, length);
} else {
add_to_dom_string(&renderer->text, string, length);
}
}
static struct dom_string *
get_rss_node_text(struct dom_node *node)
{
struct dom_node *child;
int index;
if (!node->data.element.children)
return NULL;
foreach_dom_node (node->data.element.children, child, index) {
if (child->type == DOM_NODE_TEXT)
return &child->string;
}
return NULL;
}
static struct dom_node *
get_rss_child(struct dom_node *parent, enum rss_element_type type)
{
struct dom_node *node;
int index;
if (!parent->data.element.children)
return NULL;
foreach_dom_node (parent->data.element.children, node, index) {
if (node->type == DOM_NODE_ELEMENT
&& type == node->data.element.type)
return node;
}
return NULL;
return DOM_CODE_OK;
}
static struct dom_string *
get_rss_text(struct dom_node *node, enum rss_element_type type)
{
node = get_rss_child(node, type);
node = get_dom_node_child(node, DOM_NODE_ELEMENT, type);
return node ? get_rss_node_text(node) : NULL;
if (!node) return NULL;
node = get_dom_node_child(node, DOM_NODE_TEXT, 0);
return node ? &node->string: NULL;
}
static void
@ -901,13 +897,13 @@ render_rss_item(struct dom_renderer *renderer, struct dom_node *item)
}
}
static void
enum dom_code
dom_rss_pop_document(struct dom_stack *stack, struct dom_node *root, void *data)
{
struct dom_renderer *renderer = stack->current->data;
if (!renderer->channel)
return;
return DOM_CODE_OK;
render_rss_item(renderer, renderer->channel);
@ -927,6 +923,8 @@ dom_rss_pop_document(struct dom_stack *stack, struct dom_node *root, void *data)
mem_free_if(renderer->items);
done_dom_node(root);
return DOM_CODE_OK;
}
@ -937,9 +935,9 @@ static struct dom_stack_context_info dom_rss_renderer_context_info = {
/* */ NULL,
/* DOM_NODE_ELEMENT */ dom_rss_push_element,
/* DOM_NODE_ATTRIBUTE */ NULL,
/* DOM_NODE_TEXT */ dom_rss_push_content,
/* DOM_NODE_CDATA_SECTION */ dom_rss_push_content,
/* DOM_NODE_ENTITY_REFERENCE */ dom_rss_push_content,
/* 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,
@ -976,12 +974,11 @@ render_dom_document(struct cache_entry *cached, struct document *document,
struct dom_renderer renderer;
struct conv_table *convert_table;
struct sgml_parser *parser;
enum sgml_document_type doctype;
enum sgml_parser_type parser_type;
unsigned char *string = struri(cached->uri);
size_t length = strlen(string);
struct dom_string uri = INIT_DOM_STRING(string, length);
enum sgml_parser_code code;
enum dom_code code;
convert_table = get_convert_table(head, document->options.cp,
document->options.assume_cp,
@ -1000,34 +997,35 @@ render_dom_document(struct cache_entry *cached, struct document *document,
/* FIXME: Refactor the doctype lookup. */
if (!strcasecmp("application/rss+xml", cached->content_type)) {
doctype = SGML_DOCTYPE_RSS;
renderer.doctype = SGML_DOCTYPE_RSS;
} else if (!strcasecmp("application/docbook+xml", cached->content_type)) {
doctype = SGML_DOCTYPE_DOCBOOK;
renderer.doctype = SGML_DOCTYPE_DOCBOOK;
} else if (!strcasecmp("application/xbel+xml", cached->content_type)
|| !strcasecmp("application/x-xbel", cached->content_type)
|| !strcasecmp("application/xbel", cached->content_type)) {
doctype = SGML_DOCTYPE_XBEL;
renderer.doctype = SGML_DOCTYPE_XBEL;
} else {
assertm(!strcasecmp("text/html", cached->content_type)
|| !strcasecmp("application/xhtml+xml", cached->content_type),
"Couldn't resolve doctype '%s'", cached->content_type);
doctype = SGML_DOCTYPE_HTML;
renderer.doctype = SGML_DOCTYPE_HTML;
}
parser = init_sgml_parser(parser_type, doctype, &uri, 0);
parser = init_sgml_parser(parser_type, renderer.doctype, &uri, 0);
if (!parser) return;
if (document->options.plain) {
add_dom_stack_context(&parser->stack, &renderer,
&dom_source_renderer_context_info);
} else if (doctype == SGML_DOCTYPE_RSS) {
} else if (renderer.doctype == SGML_DOCTYPE_RSS) {
add_dom_stack_context(&parser->stack, &renderer,
&dom_rss_renderer_context_info);
add_dom_config_normalizer(&parser->stack, RSS_CONFIG_FLAGS);
}
/* FIXME: When rendering this way we don't really care about the code.
@ -1048,5 +1046,6 @@ render_dom_document(struct cache_entry *cached, struct document *document,
if (renderer.find_url)
regfree(&renderer.url_regex);
#endif
done_uri(renderer.base_uri);
done_sgml_parser(parser);
}

View File

@ -14,6 +14,7 @@
#include "bfu/listmenu.h"
#include "document/document.h"
#include "document/forms.h"
#include "document/renderer.h"
#include "util/error.h"
#include "util/lists.h"
#include "util/memory.h"
@ -91,6 +92,7 @@ done_form(struct form *form)
mem_free_if(form->action);
mem_free_if(form->name);
mem_free_if(form->onsubmit);
mem_free_if(form->target);
foreach (fc, form->items) {
@ -130,6 +132,8 @@ get_form_control_link(struct document *document, struct form_control *fc)
if (fc->type == FC_HIDDEN)
return -1;
if (!document->links_sorted) sort_links(document);
for (link = 0; link < document->nlinks; link++)
if (fc == get_link_form_control(&document->links[link]))
return link;

View File

@ -32,6 +32,7 @@ struct form {
unsigned char *action;
unsigned char *name;
unsigned char *onsubmit;
unsigned char *target;
enum form_method method;

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../../../.vimrc

View File

@ -533,8 +533,7 @@ look_for_link(unsigned char **pos, unsigned char *eof, struct menu_item **menu,
}
target = get_target(options, attr);
if (!target) target = null_or_stracpy(target_base);
if (!target) target = stracpy("");
if (!target) target = stracpy(empty_string_or_(target_base));
if (!target) {
mem_free_if(label);
return 1;
@ -660,7 +659,7 @@ get_image_map(unsigned char *head, unsigned char *pos, unsigned char *eof,
struct html_element *
init_html_parser_state(struct html_context *html_context,
enum html_element_type type,
enum html_element_mortality_type type,
int align, int margin, int width)
{
html_stack_dup(html_context, type);

View File

@ -102,7 +102,7 @@ struct par_attrib {
};
/* HTML parser stack mortality info */
enum html_element_type {
enum html_element_mortality_type {
/* Elements of this type can not be removed from the stack. This type
* is created by the renderer when formatting a HTML part. */
ELEMENT_IMMORTAL,
@ -122,7 +122,7 @@ enum html_element_type {
struct html_element {
LIST_HEAD(struct html_element);
enum html_element_type type;
enum html_element_mortality_type type;
struct text_attrib attr;
struct par_attrib parattr;
@ -173,7 +173,7 @@ init_html_parser(struct uri *uri, struct document_options *options,
...));
void done_html_parser(struct html_context *html_context);
struct html_element *init_html_parser_state(struct html_context *html_context, enum html_element_type type, int align, int margin, int width);
struct html_element *init_html_parser_state(struct html_context *html_context, enum html_element_mortality_type type, int align, int margin, int width);
void done_html_parser_state(struct html_context *html_context,
struct html_element *element);

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../../../../.vimrc

View File

@ -69,7 +69,7 @@ html_form(struct html_context *html_context, unsigned char *a,
}
mem_free(al);
}
form->onsubmit = get_attr_val(a, "onsubmit", html_context->options);
al = get_attr_val(a, "name", html_context->options);
if (al) form->name = al;

View File

@ -17,6 +17,8 @@
#include "config/options.h"
#include "document/css/apply.h"
#include "document/document.h"
#include "document/view.h"
#include "document/html/frames.h"
#include "document/html/parser/general.h"
#include "document/html/parser/link.h"
@ -26,6 +28,7 @@
#include "document/html/renderer.h"
#include "document/html/tables.h"
#include "document/options.h"
#include "ecmascript/ecmascript.h"
#include "intl/charsets.h"
#include "protocol/uri.h"
#include "terminal/draw.h"
@ -37,6 +40,7 @@
#include "util/memdebug.h"
#include "util/memory.h"
#include "util/string.h"
#include "viewer/text/vs.h"
/* Unsafe macros */
#include "document/html/internal.h"
@ -343,8 +347,42 @@ imported:
}
if (html_context->part->document && *html != '^') {
struct string code, ret;
struct part *part = html_context->part;
struct document *document = part->document;
struct document_view *doc_view = document->doc_view;
struct view_state *vs = doc_view->vs;
struct ecmascript_interpreter *interpreter;
if (vs->ecmascript_fragile)
ecmascript_reset_state(vs);
interpreter = vs->ecmascript;
assert(interpreter);
if (!init_string(&code)) return;
if (!init_string(&ret)) {
done_string(&code);
return;
}
add_bytes_to_string(&code, html, *end - html);
ecmascript_eval(interpreter, &code, &ret);
done_string(&code);
if (!ret.length) {
done_string(&ret);
return;
}
/* FIXME: it doesn't work */
html_top->invisible = 0;
parse_html(ret.source, ret.source + ret.length, part, NULL,
html_context);
done_string(&ret);
#if 0
add_to_string_list(&html_context->part->document->onload_snippets,
html, *end - html);
#endif
}
#endif
}

View File

@ -127,7 +127,7 @@ kill_html_stack_item(struct html_context *html_context, struct html_element *e)
void
html_stack_dup(struct html_context *html_context, enum html_element_type type)
html_stack_dup(struct html_context *html_context, enum html_element_mortality_type type)
{
struct html_element *e;
struct html_element *ep = html_context->stack.next;

View File

@ -10,7 +10,7 @@ struct html_element *search_html_stack(struct html_context *html_context,
unsigned char *name);
void html_stack_dup(struct html_context *html_context,
enum html_element_type type);
enum html_element_mortality_type type);
void kill_html_stack_item(struct html_context *html_context,
struct html_element *e);

View File

@ -1049,6 +1049,7 @@ new_link(struct html_context *html_context, unsigned char *name, int namelen)
init_link_event_hooks(html_context, link);
document->links_sorted = 0;
return link;
}

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../../../.vimrc

View File

@ -102,7 +102,7 @@ add_document_link(struct document *document, unsigned char *uri, int length,
}
document->nlinks++;
document->links_sorted = 0;
return link;
}
@ -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

@ -39,8 +39,6 @@
#include "viewer/text/vs.h"
static void sort_links(struct document *document);
#ifdef CONFIG_ECMASCRIPT
/* XXX: This function is de facto obsolete, since we do not need to copy
* snippets around anymore (we process them in one go after the document is
@ -129,7 +127,7 @@ process_snippets(struct ecmascript_interpreter *interpreter,
if (*string->source != '^') {
/* Evaluate <script>code</script> snippet */
ecmascript_eval(interpreter, string);
ecmascript_eval(interpreter, string, NULL);
continue;
}
@ -194,7 +192,7 @@ process_snippets(struct ecmascript_interpreter *interpreter,
if (fragment) {
struct string code = INIT_STRING(fragment->data, fragment->length);
ecmascript_eval(interpreter, &code);
ecmascript_eval(interpreter, &code, NULL);
}
}
}
@ -284,7 +282,6 @@ render_document(struct view_state *vs, struct document_view *doc_view,
options->gradual_rerendering, struri(vs->uri),
doc_view, doc_view->name, vs);
#endif
name = doc_view->name;
doc_view->name = NULL;
@ -328,13 +325,18 @@ render_document(struct view_state *vs, struct document_view *doc_view,
document = get_cached_document(cached, options);
if (document) {
doc_view->document = document;
#ifdef CONFIG_ECMASCRIPT
document->doc_view = doc_view;
#endif
} else {
document = init_document(cached, options);
if (!document) return;
doc_view->document = document;
shrink_memory(0);
#ifdef CONFIG_ECMASCRIPT
document->doc_view = doc_view;
#endif
render_encoded_document(cached, document);
sort_links(document);
if (!document->title) {
@ -492,7 +494,7 @@ comp_links(struct link *l1, struct link *l2)
return (l1->number - l2->number);
}
static void
void
sort_links(struct document *document)
{
int i;
@ -501,6 +503,7 @@ sort_links(struct document *document)
if_assert_failed return;
if (!document->nlinks) return;
if (document->links_sorted) return;
assert(document->links);
if_assert_failed return;
@ -509,7 +512,9 @@ sort_links(struct document *document)
if (!document->height) return;
mem_free_if(document->lines1);
document->lines1 = mem_calloc(document->height, sizeof(*document->lines1));
mem_free_if(document->lines2);
if (!document->lines1) return;
document->lines2 = mem_calloc(document->height, sizeof(*document->lines2));
if (!document->lines2) {
@ -540,6 +545,7 @@ sort_links(struct document *document)
document->lines1[j] = &document->links[i];
}
}
document->links_sorted = 1;
}
struct conv_table *

View File

@ -12,6 +12,6 @@ struct view_state;
void render_document(struct view_state *, struct document_view *, struct document_options *);
void render_document_frames(struct session *ses, int no_cache);
struct conv_table *get_convert_table(unsigned char *head, int to_cp, int default_cp, int *from_cp, enum cp_status *cp_status, int ignore_server_cp);
void sort_links(struct document *document);
#endif

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../../.vimrc

View File

@ -2,7 +2,7 @@ top_builddir=../..
include $(top_builddir)/Makefile.config
SUBDIRS = css sgml
OBJS = node.o select.o stack.o scanner.o
OBJS = configuration.o node.o select.o stack.o scanner.o
SUBDIRS-$(CONFIG_DEBUG) += test

47
src/dom/code.h Normal file
View File

@ -0,0 +1,47 @@
#ifndef EL_DOM_CODE_H
#define EL_DOM_CODE_H
/* API Doc :: dom-code */
/** DOM status/error/exception codes
*
* These enum values are used for return codes throughout the DOM engine.
*/
enum dom_code {
/** ELinks specific codes: */
DOM_CODE_OK = 0, /*: The sane default. */
DOM_CODE_ERR = -1000, /*: Anything by DOM_CODE_OK. */
DOM_CODE_INCOMPLETE, /*: The parsing could not be completed */
DOM_CODE_FREE_NODE, /*: Discard the node */
/** Error codes: */
DOM_CODE_ALLOC_ERR, /*: Failed to allocate memory */
DOM_CODE_MAX_DEPTH_ERR, /*: Stack max depth reached */
DOM_CODE_VALUE_ERR, /*: Bad/unexpected value */
/** DOM Level 1 codes: */
DOM_CODE_INDEX_SIZE_ERR = 1,
DOM_CODE_STRING_SIZE_ERR = 2,
DOM_CODE_HIERARCHY_REQUEST_ERR = 3,
DOM_CODE_WRONG_DOCUMENT_ERR = 4,
DOM_CODE_INVALID_CHARACTER_ERR = 5,
DOM_CODE_NO_DATA_ALLOWED_ERR = 6,
DOM_CODE_NO_MODIFICATION_ALLOWED_ERR = 7,
DOM_CODE_NOT_FOUND_ERR = 8,
DOM_CODE_NOT_SUPPORTED_ERR = 9,
DOM_CODE_INUSE_ATTRIBUTE_ERR = 10,
/** Introduced in DOM Level 2: */
DOM_CODE_INVALID_STATE_ERR = 11,
DOM_CODE_SYNTAX_ERR = 12,
DOM_CODE_INVALID_MODIFICATION_ERR = 13,
DOM_CODE_NAMESPACE_ERR = 14,
DOM_CODE_INVALID_ACCESS_ERR = 15,
/** Introduced in DOM Level 3: */
DOM_CODE_VALIDATION_ERR = 16,
DOM_CODE_TYPE_MISMATCH_ERR = 17,
};
#endif

351
src/dom/configuration.c Normal file
View File

@ -0,0 +1,351 @@
/* DOM Configuration */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "elinks.h"
#include "dom/configuration.h"
#include "dom/node.h"
#include "dom/stack.h"
#include "dom/string.h"
static enum dom_code
normalize_text_node_whitespace(struct dom_node *node)
{
unsigned char buf[256];
struct dom_string string = INIT_DOM_STRING(NULL, 0);
int count = 0, i = 0;
unsigned char *text = node->string.string;
assert(node->type == DOM_NODE_TEXT);
while (i < node->string.length) {
int j;
for (j = 0; j < sizeof(buf) && i < node->string.length; i++) {
unsigned char data = text[i];
if (isspace(data)) {
if (count == 1)
continue;
data = ' ';
count = 1;
} else {
count = 0;
}
buf[j++] = data;
}
if (!add_to_dom_string(&string, buf, j)) {
done_dom_string(&string);
return DOM_CODE_ALLOC_ERR;
}
}
if (node->allocated)
done_dom_string(&node->string);
set_dom_string(&node->string, string.string, string.length);
node->allocated = 1;
return DOM_CODE_OK;
}
static enum dom_code
append_node_text(struct dom_config *config, struct dom_node *node)
{
struct dom_node *prev = get_dom_node_prev(node);
size_t length;
struct dom_string dest;
struct dom_string src;
int error = 0;
copy_struct(&src, &node->string);
if (!prev || prev->type != DOM_NODE_TEXT) {
/* Preserve text nodes with no one to append to. */
if (node->type == DOM_NODE_TEXT)
return DOM_CODE_OK;
prev = NULL;
set_dom_string(&dest, NULL, 0);
} else {
if (prev->allocated) {
copy_struct(&dest, &prev->string);
} else {
set_dom_string(&dest, NULL, 0);
if (!add_to_dom_string(&dest, prev->string.string, prev->string.length))
return DOM_CODE_ALLOC_ERR;
set_dom_string(&prev->string, dest.string, dest.length);
prev->allocated = 1;
}
}
length = dest.length;
switch (node->type) {
case DOM_NODE_CDATA_SECTION:
case DOM_NODE_TEXT:
if (!add_to_dom_string(&dest, src.string, src.length))
error = 1;
break;
case DOM_NODE_ENTITY_REFERENCE:
/* FIXME: Until we will have uniform encoding at this point
* (UTF-8) we just add the entity reference unexpanded assuming
* that convert_string() will eventually do the work of
* expanding it. */
if (!add_to_dom_string(&dest, "&", 1)
|| !add_to_dom_string(&dest, src.string, src.length)
|| !add_to_dom_string(&dest, ";", 1)) {
error = 1;
}
break;
default:
INTERNAL("Cannot append from node %d", node->type);
}
if (error) {
if (prev)
prev->string.length = length;
else
done_dom_string(&dest);
return DOM_CODE_ALLOC_ERR;
}
if (prev) {
copy_struct(&prev->string, &dest);
if ((config->flags & DOM_CONFIG_NORMALIZE_WHITESPACE)
&& node->type != DOM_NODE_ENTITY_REFERENCE) {
/* XXX: Ignore errors since we want to always
* free the appended node at this point. */
normalize_text_node_whitespace(prev);
}
return DOM_CODE_FREE_NODE;
} else {
int was_cdata_section = node->type == DOM_NODE_CDATA_SECTION;
node->type = DOM_NODE_TEXT;
memset(&node->data, 0, sizeof(node->data));
node->allocated = 1;
copy_struct(&node->string, &dest);
if ((config->flags & DOM_CONFIG_NORMALIZE_WHITESPACE)
&& was_cdata_section) {
/* XXX: Ignore errors since we want to always ok the
* append. */
normalize_text_node_whitespace(node);
}
return DOM_CODE_OK;
}
}
static enum dom_code
dom_normalize_node_end(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_config *config = stack->current->data;
enum dom_code code = DOM_CODE_OK;
switch (node->type) {
case DOM_NODE_ELEMENT:
if ((config->flags & DOM_CONFIG_UNKNOWN)
&& !node->data.element.type) {
/* Drop elements that are not known from the built-in
* node info. */
code = DOM_CODE_FREE_NODE;
}
break;
case DOM_NODE_ATTRIBUTE:
if ((config->flags & DOM_CONFIG_UNKNOWN)
&& !node->data.attribute.type) {
/* Drop elements that are not known from the built-in
* node info. */
code = DOM_CODE_FREE_NODE;
}
break;
case DOM_NODE_PROCESSING_INSTRUCTION:
if ((config->flags & DOM_CONFIG_UNKNOWN)
&& !node->data.proc_instruction.type) {
/* Drop elements that are not known from the built-in
* node info. */
code = DOM_CODE_FREE_NODE;
}
break;
case DOM_NODE_TEXT:
if (!(config->flags & DOM_CONFIG_ELEMENT_CONTENT_WHITESPACE)
&& node->data.text.only_space) {
/* Discard all Text nodes that contain
* whitespaces in element content]. */
code = DOM_CODE_FREE_NODE;
} else {
code = append_node_text(config, node);
}
break;
case DOM_NODE_COMMENT:
if (!(config->flags & DOM_CONFIG_COMMENTS)) {
/* Discard all comments. */
code = DOM_CODE_FREE_NODE;
}
break;
case DOM_NODE_CDATA_SECTION:
if (!(config->flags & DOM_CONFIG_CDATA_SECTIONS)) {
/* Transform CDATASection nodes into Text nodes. The new Text
* node is then combined with any adjacent Text node. */
code = append_node_text(config, node);
}
break;
case DOM_NODE_ENTITY_REFERENCE:
if (!(config->flags & DOM_CONFIG_ENTITIES)) {
/* Remove all EntityReference nodes from the document,
* putting the entity expansions directly in their place. Text
* nodes are normalized. Only unexpanded entity references are
* kept in the document. */
code = append_node_text(config, node);
}
break;
case DOM_NODE_DOCUMENT:
mem_free(config);
break;
default:
break;
}
return code;
}
enum dom_code
dom_normalize_text(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_config *config = stack->current->data;
if (config->flags & DOM_CONFIG_NORMALIZE_WHITESPACE) {
/* Normalize whitespace in the text. */
return normalize_text_node_whitespace(node);
}
return DOM_CODE_OK;
}
static struct dom_stack_context_info dom_config_normalizer_context = {
/* Object size: */ 0,
/* Push: */
{
/* */ NULL,
/* DOM_NODE_ELEMENT */ NULL,
/* DOM_NODE_ATTRIBUTE */ NULL,
/* DOM_NODE_TEXT */ dom_normalize_text,
/* 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,
},
/* Pop: */
{
/* */ NULL,
/* DOM_NODE_ELEMENT */ dom_normalize_node_end,
/* DOM_NODE_ATTRIBUTE */ dom_normalize_node_end,
/* DOM_NODE_TEXT */ dom_normalize_node_end,
/* DOM_NODE_CDATA_SECTION */ dom_normalize_node_end,
/* DOM_NODE_ENTITY_REFERENCE */ dom_normalize_node_end,
/* DOM_NODE_ENTITY */ dom_normalize_node_end,
/* DOM_NODE_PROC_INSTRUCTION */ dom_normalize_node_end,
/* DOM_NODE_COMMENT */ dom_normalize_node_end,
/* DOM_NODE_DOCUMENT */ dom_normalize_node_end,
/* DOM_NODE_DOCUMENT_TYPE */ dom_normalize_node_end,
/* DOM_NODE_DOCUMENT_FRAGMENT */ dom_normalize_node_end,
/* DOM_NODE_NOTATION */ dom_normalize_node_end,
}
};
struct dom_config *
add_dom_config_normalizer(struct dom_stack *stack, enum dom_config_flag flags)
{
struct dom_config *config;
config = mem_calloc(1, sizeof(*config));
if (!config) return NULL;
config->flags = flags;
if (add_dom_stack_context(stack, config, &dom_config_normalizer_context))
return config;
mem_free(config);
return NULL;
}
struct dom_config_info {
struct dom_string name;
enum dom_config_flag flag;
};
#define DOM_CONFIG(name, flag) \
{ STATIC_DOM_STRING(name), (flag) }
static struct dom_config_info dom_config_info[] = {
DOM_CONFIG("cdata-sections", DOM_CONFIG_CDATA_SECTIONS),
DOM_CONFIG("comments", DOM_CONFIG_COMMENTS),
DOM_CONFIG("element-content-whitespace",DOM_CONFIG_ELEMENT_CONTENT_WHITESPACE),
DOM_CONFIG("entities", DOM_CONFIG_ENTITIES),
DOM_CONFIG("normalize-characters", DOM_CONFIG_NORMALIZE_CHARACTERS),
DOM_CONFIG("unknown", DOM_CONFIG_UNKNOWN),
DOM_CONFIG("normalize-whitespace", DOM_CONFIG_NORMALIZE_WHITESPACE),
};
static enum dom_config_flag
get_dom_config_flag(struct dom_string *name)
{
int i;
for (i = 0; i < sizeof_array(dom_config_info); i++)
if (!dom_string_casecmp(&dom_config_info[i].name, name))
return dom_config_info[i].flag;
return 0;
}
enum dom_config_flag
parse_dom_config(unsigned char *flaglist, unsigned char separator)
{
enum dom_config_flag flags = 0;
while (flaglist) {
unsigned char *end = separator ? strchr(flaglist, separator) : NULL;
int length = end ? end - flaglist : strlen(flaglist);
struct dom_string name = INIT_DOM_STRING(flaglist, length);
flags |= get_dom_config_flag(&name);
if (end) end++;
flaglist = end;
}
return flags;
}

94
src/dom/configuration.h Normal file
View File

@ -0,0 +1,94 @@
#ifndef EL__DOM_CONFIGURATION_H
#define EL__DOM_CONFIGURATION_H
struct dom_node;
struct dom_stack;
/* API Doc :: dom-config */
/** DOM Configuration
*
* The DOMConfiguration interface represents the configuration of a document.
* Using the configuration, it is possible to change the behaviour of how
* document normalization is done, such as replacing the CDATASection nodes
* with Text nodes.
*
* Note: Parameters are similar to features and properties used in SAX2 [SAX].
*
* The following list of parameters defined in the DOM: */
enum dom_config_flag {
/** "cdata-sections"
*
* The default is true and will keep CDATASection nodes in the
* document. When false, CDATASection nodes in the document are
* transformed into Text nodes. The new Text node is then combined with
* any adjacent Text node. */
DOM_CONFIG_CDATA_SECTIONS = 1,
/** "comments"
*
* If true (the default) keep Comment nodes in the document, else
* discard them. */
DOM_CONFIG_COMMENTS = 2,
/** "element-content-whitespace"
*
* The default is true and will keep all whitespaces in the document.
* When false, discard all Text nodes that contain only whitespaces. */
DOM_CONFIG_ELEMENT_CONTENT_WHITESPACE = 4,
/** "entities"
*
* When true (the default) keep EntityReference nodes in the document.
* When false, remove all EntityReference nodes from the document,
* putting the entity expansions directly in their place. Text nodes
* are normalized. Only unexpanded entity references are kept in the
* document. Note: This parameter does not affect Entity nodes. */
DOM_CONFIG_ENTITIES = 8,
/** "normalize-characters"
*
* The default is false, not to perform character normalization, else
* fully normalized the characters in the document as defined in
* appendix B of [XML 1.1]. */
DOM_CONFIG_NORMALIZE_CHARACTERS = 16,
/** "unknown"
*
* If false (default) nothing is done, else elements and attributes
* that are not known according to the built-in node info are
* discarded. */
DOM_CONFIG_UNKNOWN = 32,
/** "normalize-whitespace"
*
* If false (default) nothing is done, else all text nodes are
* normalized so that sequences of space characters are changed to
* being only a single space. */
DOM_CONFIG_NORMALIZE_WHITESPACE = 64,
};
struct dom_error;
struct dom_config {
enum dom_config_flag flags; /*: DOM configuration flags. */
/** FIXME: "error-handler"
*
* Contains an error handler. If an error is encountered in the
* document, this handler is called. When called, DOMError.relatedData
* will contain the closest node to where the error occurred. If the
* implementation is unable to determine the node where the error
* occurs, DOMError.relatedData will contain the Document node.
*/
void (*error_handler)(struct dom_config *, struct dom_error *);
};
struct dom_config *
add_dom_config_normalizer(struct dom_stack *stack, enum dom_config_flag flags);
enum dom_config_flag
parse_dom_config(unsigned char *flaglist, unsigned char separator);
#endif

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../../../.vimrc

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

@ -1,25 +0,0 @@
#ifndef EL_DOM_DOM_H
#define EL_DOM_DOM_H
enum dom_exception_code {
DOM_ERR_NONE = 0,
DOM_ERR_INDEX_SIZE = 1,
DOM_ERR_STRING_SIZE = 2,
DOM_ERR_HIERARCHY_REQUEST = 3,
DOM_ERR_WRONG_DOCUMENT = 4,
DOM_ERR_INVALID_CHARACTER = 5,
DOM_ERR_NO_DATA_ALLOWED = 6,
DOM_ERR_NO_MODIFICATION_ALLOWED = 7,
DOM_ERR_NOT_FOUND = 8,
DOM_ERR_NOT_SUPPORTED = 9,
DOM_ERR_INUSE_ATTRIBUTE = 10,
/* Introduced in DOM Level 2: */
DOM_ERR_INVALID_STATE = 11,
DOM_ERR_SYNTAX = 12,
DOM_ERR_INVALID_MODIFICATION = 13,
DOM_ERR_NAMESPACE = 14,
DOM_ERR_INVALID_ACCESS = 15,
};
#endif

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);
@ -202,7 +203,7 @@ struct dom_node *
get_dom_node_map_entry(struct dom_node_list *list, enum dom_node_type type,
uint16_t subtype, struct dom_string *name)
{
struct dom_node node = { type, INIT_DOM_STRING(name->string, name->length) };
struct dom_node node = { type, 0, INIT_DOM_STRING(name->string, name->length) };
struct dom_node_search search = INIT_DOM_NODE_SEARCH(&node, list);
if (subtype) {
@ -225,16 +226,15 @@ get_dom_node_map_entry(struct dom_node_list *list, enum dom_node_type type,
return dom_node_list_bsearch(&search, list);
}
int
get_dom_node_list_index(struct dom_node *parent, struct dom_node *node)
static int
get_dom_node_list_pos(struct dom_node_list *list, struct dom_node *node)
{
struct dom_node_list **list = get_dom_node_list(parent, node);
struct dom_node *entry;
int i;
if (!list) return -1;
assert(list);
foreach_dom_node (*list, entry, i) {
foreach_dom_node (list, entry, i) {
if (entry == node)
return i;
}
@ -242,12 +242,98 @@ get_dom_node_list_index(struct dom_node *parent, struct dom_node *node)
return -1;
}
int
get_dom_node_list_index(struct dom_node *parent, struct dom_node *node)
{
struct dom_node_list **list = get_dom_node_list(parent, node);
return list ? get_dom_node_list_pos(*list, node) : -1;
}
struct dom_node *
get_dom_node_prev(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 > 0)
return (*list)->entries[index - 1];
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)
{
struct dom_node_list **list;
struct dom_node *node;
int index;
list = get_dom_node_list_by_type(parent, type);
if (!list) return NULL;
foreach_dom_node (*list, node, index) {
if (node->type != type)
continue;
if (!subtype) return node;
switch (type) {
case DOM_NODE_ELEMENT:
if (node->data.element.type == subtype)
return node;
break;
case DOM_NODE_ATTRIBUTE:
if (node->data.attribute.type == subtype)
return node;
break;
case DOM_NODE_PROCESSING_INSTRUCTION:
if (node->data.attribute.type == subtype)
return node;
break;
default:
return node;
}
}
return NULL;
}
/* Nodes */
struct dom_node *
init_dom_node_(unsigned char *file, int line,
struct dom_node *parent, enum dom_node_type type,
struct dom_string *string)
struct dom_string *string, int allocated)
{
#ifdef DEBUG_MEMLEAK
struct dom_node *node = debug_mem_calloc(file, line, 1, sizeof(*node));
@ -259,7 +345,23 @@ init_dom_node_(unsigned char *file, int line,
node->type = type;
node->parent = parent;
copy_dom_string(&node->string, string);
/* 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);
@ -292,17 +394,11 @@ done_dom_node_data(struct dom_node *node)
switch (node->type) {
case DOM_NODE_ATTRIBUTE:
if (data->attribute.allocated)
done_dom_string(&node->string);
if (node->allocated)
done_dom_string(&data->attribute.value);
break;
case DOM_NODE_DOCUMENT:
if (data->document.element_ids)
free_hash(data->document.element_ids);
if (data->document.meta_nodes)
done_dom_node_list(data->document.meta_nodes);
if (data->document.children)
done_dom_node_list(data->document.children);
break;
@ -315,20 +411,19 @@ done_dom_node_data(struct dom_node *node)
done_dom_node_list(data->element.map);
break;
case DOM_NODE_TEXT:
if (data->text.allocated)
done_dom_string(&node->string);
break;
case DOM_NODE_PROCESSING_INSTRUCTION:
if (data->proc_instruction.map)
done_dom_node_list(data->proc_instruction.map);
if (node->allocated)
done_dom_string(&data->proc_instruction.instruction);
break;
default:
break;
}
if (node->allocated)
done_dom_string(&node->string);
mem_free(node);
}
@ -343,7 +438,6 @@ done_dom_node(struct dom_node *node)
switch (parent->type) {
case DOM_NODE_DOCUMENT:
del_from_dom_node_list(data->document.meta_nodes, node);
del_from_dom_node_list(data->document.children, node);
break;
@ -370,11 +464,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);
@ -440,18 +534,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

@ -3,9 +3,9 @@
#define EL_DOM_NODE_H
#include "dom/string.h"
#include "util/hash.h"
struct dom_node_list;
struct dom_document;
enum dom_node_type {
DOM_NODE_UNKNOWN = 0, /* for internal purpose only */
@ -27,27 +27,15 @@ enum dom_node_type {
};
/* Following is the node specific datastructures. They may contain no more
* than 3 pointers or something equivalent. */
struct dom_node_id_item {
/* The attibute node containing the id value */
struct dom_node *id_attribute;
/* The node with the @id attribute */
struct dom_node *node;
};
* than 4 pointers or something equivalent. */
/* The document URI is stored in the string / length members. */
struct dom_document_node {
/* The document URI is stored in the string / length members. */
/* An id to node hash for fast lookup. */
struct hash *element_ids; /* -> {struct dom_node_id_item} */
/* Any meta data the root node carries such as document type nodes,
* entity and notation map nodes and maybe some internal CSS stylesheet
* node. */
struct dom_node_list *meta_nodes;
/* The document. */
struct dom_document *document;
/* The child nodes. May be NULL. Ordered like they where inserted. */
/* FIXME: Should be just one element (root) node reference. */
struct dom_node_list *children;
};
@ -111,13 +99,13 @@ 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;
/* Was the node->string allocated */
unsigned int allocated:1;
/* Has the node->string been converted to internal charset. */
unsigned int converted:1;
@ -127,9 +115,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 {
@ -140,9 +125,6 @@ struct dom_text_node {
* In order to quickly identify such nodes this member is used. */
unsigned int only_space:1;
/* Was the node->string allocated */
unsigned int allocated:1;
/* Has the node->string been converted to internal charset. */
unsigned int converted:1;
};
@ -151,9 +133,8 @@ enum dom_proc_instruction_type {
DOM_PROC_INSTRUCTION,
/* Keep this group sorted */
DOM_PROC_INSTRUCTION_DBHTML, /* DocBook toolchain instruction */
DOM_PROC_INSTRUCTION_ELINKS, /* Internal instruction hook */
DOM_PROC_INSTRUCTION_XML, /* XML instructions */
DOM_PROC_INSTRUCTION_XML, /* XML header */
DOM_PROC_INSTRUCTION_XML_STYLESHEET, /* XML stylesheet link */
DOM_PROC_INSTRUCTION_TYPES
};
@ -183,12 +164,13 @@ union dom_node_data {
struct dom_id entity;
struct dom_proc_instruction_node proc_instruction;
/* Node types without a union member yet
/* Node types without a union member yet (mostly because it hasn't
* been necessary):
*
* DOM_NODE_CDATA_SECTION,
* DOM_NODE_COMMENT,
* DOM_NODE_DOCUMENT_FRAGMENT,
* DOM_NODE_ENTITY_REFERENCE,
* DOM_NODE_CDATA_SECTION: Use dom_text_node?
* DOM_NODE_DOCUMENT_FRAGMENT: struct dom_node_list children;
* DOM_NODE_ENTITY_REFERENCE: unicode_val_T
* DOM_NODE_COMMENT
*/
};
@ -198,6 +180,9 @@ struct dom_node {
/* The type of the node */
uint16_t type; /* -> enum dom_node_type */
/* Was the node string allocated? */
unsigned int allocated:1;
/* Can contain either stuff like element name or for attributes the
* attribute name. */
struct dom_string string;
@ -243,6 +228,17 @@ int get_dom_node_list_index(struct dom_node *parent, struct dom_node *node);
* @list is already sorted properly. */
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,
int16_t child_subtype);
/* Looks up the @node_map for a node matching the requested type and name.
* The @subtype maybe be 0 indication unknown subtype and only name should be
* tested else it will indicate either the element or attribute private
@ -252,12 +248,21 @@ get_dom_node_map_entry(struct dom_node_list *node_map,
enum dom_node_type type, uint16_t subtype,
struct dom_string *name);
/* Removes the node and all its children and free()s itself */
void done_dom_node(struct dom_node *node);
/* The allocated argument is used as the value of node->allocated if >= 0.
* Use -1 to default node->allocated to the value of parent->allocated. */
struct dom_node *
init_dom_node_(unsigned char *file, int line,
struct dom_node *parent, enum dom_node_type type,
struct dom_string *string);
#define init_dom_node(type, string) init_dom_node_(__FILE__, __LINE__, NULL, type, string)
#define add_dom_node(parent, type, string) init_dom_node_(__FILE__, __LINE__, parent, type, string)
struct dom_string *string, int allocated);
#define init_dom_node(type, string, allocated) \
init_dom_node_(__FILE__, __LINE__, NULL, type, string, allocated)
#define add_dom_node(parent, type, string) \
init_dom_node_(__FILE__, __LINE__, parent, type, string, -1)
#define add_dom_element(parent, string) \
add_dom_node(parent, DOM_NODE_ELEMENT, string)
@ -269,7 +274,16 @@ add_dom_attribute(struct dom_node *parent, struct dom_string *name,
struct dom_node *node = add_dom_node(parent, DOM_NODE_ATTRIBUTE, name);
if (node && value) {
copy_dom_string(&node->data.attribute.value, value);
struct dom_string *str = &node->data.attribute.value;
if (node->allocated) {
if (!init_dom_string(str, value->string, value->length)) {
done_dom_node(node);
return NULL;
}
} else {
copy_dom_string(str, value);
}
}
return node;
@ -282,15 +296,21 @@ add_dom_proc_instruction(struct dom_node *parent, struct dom_string *string,
struct dom_node *node = add_dom_node(parent, DOM_NODE_PROCESSING_INSTRUCTION, string);
if (node && instruction) {
copy_dom_string(&node->data.proc_instruction.instruction, instruction);
struct dom_string *str = &node->data.proc_instruction.instruction;
if (node->allocated) {
if (!init_dom_string(str, instruction->string, instruction->length)) {
done_dom_node(node);
return NULL;
}
} else {
copy_dom_string(str, instruction);
}
}
return node;
}
/* Removes the node and all its children and free()s itself */
void done_dom_node(struct dom_node *node);
/* Compare two nodes returning non-zero if they differ. */
int dom_node_casecmp(struct dom_node *node1, struct dom_node *node2);
@ -304,17 +324,17 @@ struct dom_string *get_dom_node_value(struct dom_node *node);
/* Returns the name used for identifying the node type. */
struct dom_string *get_dom_node_type_name(enum dom_node_type type);
/* Based on the type of the parent and the node return a proper list
/* Based on the type of the parent and the node type return a proper list
* or NULL. This is useful when adding a node to a parent node. */
static inline struct dom_node_list **
get_dom_node_list(struct dom_node *parent, struct dom_node *node)
get_dom_node_list_by_type(struct dom_node *parent, enum dom_node_type type)
{
switch (parent->type) {
case DOM_NODE_DOCUMENT:
return &parent->data.document.children;
case DOM_NODE_ELEMENT:
switch (node->type) {
switch (type) {
case DOM_NODE_ATTRIBUTE:
return &parent->data.element.map;
@ -323,7 +343,7 @@ get_dom_node_list(struct dom_node *parent, struct dom_node *node)
}
case DOM_NODE_DOCUMENT_TYPE:
switch (node->type) {
switch (type) {
case DOM_NODE_ENTITY:
return &parent->data.document_type.entities;
@ -335,7 +355,7 @@ get_dom_node_list(struct dom_node *parent, struct dom_node *node)
}
case DOM_NODE_PROCESSING_INSTRUCTION:
switch (node->type) {
switch (type) {
case DOM_NODE_ATTRIBUTE:
return &parent->data.proc_instruction.map;
@ -348,4 +368,7 @@ get_dom_node_list(struct dom_node *parent, struct dom_node *node)
}
}
#define get_dom_node_list(parent, node) \
get_dom_node_list_by_type(parent, (node)->type)
#endif

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

@ -7,7 +7,7 @@
#include "elinks.h"
#include "dom/css/scanner.h"
#include "dom/dom.h"
#include "dom/code.h"
#include "dom/node.h"
#include "dom/scanner.h"
#include "dom/select.h"
@ -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),
@ -80,7 +80,7 @@ get_dom_select_pseudo(struct dom_scanner_token *token)
}
/* Parses attribute selector. For example '[foo="bar"]' or '[foo|="boo"]'. */
static enum dom_exception_code
static enum dom_code
parse_dom_select_attribute(struct dom_select_node *sel, struct dom_scanner *scanner)
{
struct dom_scanner_token *token = get_dom_scanner_token(scanner);
@ -88,25 +88,25 @@ parse_dom_select_attribute(struct dom_select_node *sel, struct dom_scanner *scan
/* Get '['. */
if (token->type != '[')
return DOM_ERR_INVALID_STATE;
return DOM_CODE_SYNTAX_ERR;
/* Get the attribute name. */
token = get_next_dom_scanner_token(scanner);
if (!token || token->type != CSS_TOKEN_IDENT)
return DOM_ERR_SYNTAX;
return DOM_CODE_SYNTAX_ERR;
copy_dom_string(&sel->node.string, &token->string);
/* Get the optional '=' combo or ending ']'. */
token = get_next_dom_scanner_token(scanner);
if (!token) return DOM_ERR_SYNTAX;
if (!token) return DOM_CODE_SYNTAX_ERR;
switch (token->type) {
case ']':
sel->match.attribute |= DOM_SELECT_ATTRIBUTE_ANY;
return DOM_ERR_NONE;
return DOM_CODE_OK;
case CSS_TOKEN_SELECT_SPACE_LIST:
sel->match.attribute |= DOM_SELECT_ATTRIBUTE_SPACE_LIST;
@ -129,13 +129,13 @@ parse_dom_select_attribute(struct dom_select_node *sel, struct dom_scanner *scan
break;
default:
return DOM_ERR_SYNTAX;
return DOM_CODE_SYNTAX_ERR;
}
/* Get the required value. */
token = get_next_dom_scanner_token(scanner);
if (!token) return DOM_ERR_SYNTAX;
if (!token) return DOM_CODE_SYNTAX_ERR;
switch (token->type) {
case CSS_TOKEN_IDENT:
@ -144,16 +144,16 @@ parse_dom_select_attribute(struct dom_select_node *sel, struct dom_scanner *scan
break;
default:
return DOM_ERR_SYNTAX;
return DOM_CODE_SYNTAX_ERR;
}
/* Get the ending ']'. */
token = get_next_dom_scanner_token(scanner);
if (token && token->type == ']')
return DOM_ERR_NONE;
return DOM_CODE_OK;
return DOM_ERR_SYNTAX;
return DOM_CODE_SYNTAX_ERR;
}
/* Parse:
@ -190,7 +190,7 @@ get_scanner_token_number(struct dom_scanner_token *token)
}
/* Parses the '(...)' part of ':nth-of-type(...)' and ':nth-child(...)'. */
static enum dom_exception_code
static enum dom_code
parse_dom_select_nth_arg(struct dom_select_nth_match *nth, struct dom_scanner *scanner)
{
struct dom_scanner_token *token = get_next_dom_scanner_token(scanner);
@ -198,11 +198,11 @@ parse_dom_select_nth_arg(struct dom_select_nth_match *nth, struct dom_scanner *s
int number = -1;
if (!token || token->type != '(')
return DOM_ERR_SYNTAX;
return DOM_CODE_SYNTAX_ERR;
token = get_next_dom_scanner_token(scanner);
if (!token)
return DOM_ERR_SYNTAX;
return DOM_CODE_SYNTAX_ERR;
switch (token->type) {
case CSS_TOKEN_IDENT:
@ -220,59 +220,59 @@ parse_dom_select_nth_arg(struct dom_select_nth_match *nth, struct dom_scanner *s
}
if (skip_css_tokens(scanner, ')'))
return DOM_ERR_NONE;
return DOM_CODE_OK;
return DOM_ERR_SYNTAX;
return DOM_CODE_SYNTAX_ERR;
case '-':
sign = -1;
token = get_next_dom_scanner_token(scanner);
if (!token) return DOM_ERR_SYNTAX;
if (!token) return DOM_CODE_SYNTAX_ERR;
if (token->type != CSS_TOKEN_IDENT)
break;
if (token->type != CSS_TOKEN_NUMBER)
return DOM_ERR_SYNTAX;
return DOM_CODE_SYNTAX_ERR;
/* Fall-through */
case CSS_TOKEN_NUMBER:
number = get_scanner_token_number(token);
if (number < 0)
return DOM_ERR_INVALID_STATE;
return DOM_CODE_VALUE_ERR;
token = get_next_dom_scanner_token(scanner);
if (!token) return DOM_ERR_SYNTAX;
if (!token) return DOM_CODE_SYNTAX_ERR;
break;
default:
return DOM_ERR_SYNTAX;
return DOM_CODE_SYNTAX_ERR;
}
/* The rest can contain n+ part */
switch (token->type) {
case CSS_TOKEN_IDENT:
if (!dom_scanner_token_contains(token, "n"))
return DOM_ERR_SYNTAX;
return DOM_CODE_SYNTAX_ERR;
nth->step = sign * number;
token = get_next_dom_scanner_token(scanner);
if (!token) return DOM_ERR_SYNTAX;
if (!token) return DOM_CODE_SYNTAX_ERR;
if (token->type != '+')
break;
token = get_next_dom_scanner_token(scanner);
if (!token) return DOM_ERR_SYNTAX;
if (!token) return DOM_CODE_SYNTAX_ERR;
if (token->type != CSS_TOKEN_NUMBER)
break;
number = get_scanner_token_number(token);
if (number < 0)
return DOM_ERR_INVALID_STATE;
return DOM_CODE_VALUE_ERR;
nth->index = sign * number;
break;
@ -283,19 +283,19 @@ parse_dom_select_nth_arg(struct dom_select_nth_match *nth, struct dom_scanner *s
}
if (skip_css_tokens(scanner, ')'))
return DOM_ERR_NONE;
return DOM_CODE_OK;
return DOM_ERR_SYNTAX;
return DOM_CODE_SYNTAX_ERR;
}
/* Parse a pseudo-class or -element with the syntax: ':<ident>'. */
static enum dom_exception_code
static enum dom_code
parse_dom_select_pseudo(struct dom_select *select, struct dom_select_node *sel,
struct dom_scanner *scanner)
{
struct dom_scanner_token *token = get_dom_scanner_token(scanner);
enum dom_select_pseudo pseudo;
enum dom_exception_code code;
enum dom_code code;
/* Skip double :'s in front of some pseudo's (::first-line, etc.) */
do {
@ -303,12 +303,12 @@ parse_dom_select_pseudo(struct dom_select *select, struct dom_select_node *sel,
} while (token && token->type == ':');
if (!token || token->type != CSS_TOKEN_IDENT)
return DOM_ERR_SYNTAX;
return DOM_CODE_SYNTAX_ERR;
pseudo = get_dom_select_pseudo(token);
switch (pseudo) {
case DOM_SELECT_PSEUDO_UNKNOWN:
return DOM_ERR_NOT_FOUND;
return DOM_CODE_ERR;
case DOM_SELECT_PSEUDO_CONTAINS:
/* FIXME: E:contains("text") */
@ -317,7 +317,7 @@ parse_dom_select_pseudo(struct dom_select *select, struct dom_select_node *sel,
case DOM_SELECT_PSEUDO_NTH_CHILD:
case DOM_SELECT_PSEUDO_NTH_LAST_CHILD:
code = parse_dom_select_nth_arg(&sel->nth_child, scanner);
if (code != DOM_ERR_NONE)
if (code != DOM_CODE_OK)
return code;
sel->match.element |= DOM_SELECT_ELEMENT_NTH_CHILD;
@ -341,7 +341,7 @@ parse_dom_select_pseudo(struct dom_select *select, struct dom_select_node *sel,
case DOM_SELECT_PSEUDO_NTH_TYPE:
case DOM_SELECT_PSEUDO_NTH_LAST_TYPE:
code = parse_dom_select_nth_arg(&sel->nth_type, scanner);
if (code != DOM_ERR_NONE)
if (code != DOM_CODE_OK)
return code;
sel->match.element |= DOM_SELECT_ELEMENT_NTH_TYPE;
@ -375,7 +375,7 @@ parse_dom_select_pseudo(struct dom_select *select, struct dom_select_node *sel,
select->pseudo |= pseudo;
}
return DOM_ERR_NONE;
return DOM_CODE_OK;
}
/* The element relation flags are mutual exclusive. This macro can be used
@ -384,7 +384,7 @@ parse_dom_select_pseudo(struct dom_select *select, struct dom_select_node *sel,
((sel)->match.element & DOM_SELECT_RELATION_FLAGS)
/* Parse a CSS3 selector and add selector nodes to the @select struct. */
static enum dom_exception_code
static enum dom_code
parse_dom_select(struct dom_select *select, struct dom_stack *stack,
struct dom_string *string)
{
@ -397,7 +397,7 @@ parse_dom_select(struct dom_select *select, struct dom_stack *stack,
while (dom_scanner_has_tokens(&scanner)) {
struct dom_scanner_token *token = get_dom_scanner_token(&scanner);
enum dom_exception_code code;
enum dom_code code;
struct dom_select_node *select_node;
assert(token);
@ -430,14 +430,14 @@ parse_dom_select(struct dom_select *select, struct dom_stack *stack,
case '[':
sel.node.type = DOM_NODE_ATTRIBUTE;
code = parse_dom_select_attribute(&sel, &scanner);
if (code != DOM_ERR_NONE)
if (code != DOM_CODE_OK)
return code;
break;
case '.':
token = get_next_dom_scanner_token(&scanner);
if (!token || token->type != CSS_TOKEN_IDENT)
return DOM_ERR_SYNTAX;
return DOM_CODE_SYNTAX_ERR;
sel.node.type = DOM_NODE_ATTRIBUTE;
sel.match.attribute |= DOM_SELECT_ATTRIBUTE_SPACE_LIST;
@ -447,30 +447,30 @@ parse_dom_select(struct dom_select *select, struct dom_stack *stack,
case ':':
code = parse_dom_select_pseudo(select, &sel, &scanner);
if (code != DOM_ERR_NONE)
if (code != DOM_CODE_OK)
return code;
break;
case '>':
if (get_element_relation(&sel) != DOM_SELECT_RELATION_DESCENDANT)
return DOM_ERR_SYNTAX;
return DOM_CODE_SYNTAX_ERR;
sel.match.element |= DOM_SELECT_RELATION_DIRECT_CHILD;
break;
case '+':
if (get_element_relation(&sel) != DOM_SELECT_RELATION_DESCENDANT)
return DOM_ERR_SYNTAX;
return DOM_CODE_SYNTAX_ERR;
sel.match.element |= DOM_SELECT_RELATION_DIRECT_ADJACENT;
break;
case '~':
if (get_element_relation(&sel) != DOM_SELECT_RELATION_DESCENDANT)
return DOM_ERR_SYNTAX;
return DOM_CODE_SYNTAX_ERR;
sel.match.element |= DOM_SELECT_RELATION_INDIRECT_ADJACENT;
break;
default:
return DOM_ERR_SYNTAX;
return DOM_CODE_SYNTAX_ERR;
}
skip_dom_scanner_token(&scanner);
@ -496,7 +496,7 @@ parse_dom_select(struct dom_select *select, struct dom_stack *stack,
if (!add_to_dom_node_list(list, node, index)) {
done_dom_node(node);
return DOM_ERR_INVALID_STATE;
return DOM_CODE_ALLOC_ERR;
}
node->parent = parent;
@ -506,8 +506,9 @@ parse_dom_select(struct dom_select *select, struct dom_stack *stack,
select->selector = select_node;
}
if (!push_dom_node(stack, &select_node->node))
return DOM_ERR_INVALID_STATE;
code = push_dom_node(stack, &select_node->node);
if (code != DOM_CODE_OK)
return code;
if (select_node->node.type != DOM_NODE_ELEMENT)
pop_dom_node(stack);
@ -516,9 +517,9 @@ parse_dom_select(struct dom_select *select, struct dom_stack *stack,
}
if (select->selector)
return DOM_ERR_NONE;
return DOM_CODE_OK;
return DOM_ERR_INVALID_STATE;
return DOM_CODE_ERR;
}
/* Basically this is just a wrapper for parse_dom_select() to ease error
@ -528,7 +529,7 @@ init_dom_select(enum dom_select_syntax syntax, struct dom_string *string)
{
struct dom_select *select = mem_calloc(1, sizeof(select));
struct dom_stack stack;
enum dom_exception_code code;
enum dom_code code;
init_dom_stack(&stack, DOM_STACK_FLAG_NONE);
add_dom_stack_tracer(&stack, "init-select: ");
@ -536,7 +537,7 @@ init_dom_select(enum dom_select_syntax syntax, struct dom_string *string)
code = parse_dom_select(select, &stack, string);
done_dom_stack(&stack);
if (code == DOM_ERR_NONE)
if (code == DOM_CODE_OK)
return select;
done_dom_select(select);
@ -897,7 +898,7 @@ match_element_selector(struct dom_select_node *selector, struct dom_node *node,
#define get_dom_select_data(stack) ((stack)->current->data)
/* Matches an element node being visited against the current selector stack. */
static void
enum dom_code
dom_select_push_element(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_select_data *select_data = get_dom_select_data(stack);
@ -921,11 +922,13 @@ dom_select_push_element(struct dom_stack *stack, struct dom_node *node, void *da
if (selector)
push_dom_node(&select_data->stack, &selector->node);
}
return DOM_CODE_OK;
}
/* Ensures that nodes, no longer 'reachable' on the stack do not have any
* states associated with them on the select data stack. */
static void
enum dom_code
dom_select_pop_element(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_select_data *select_data = get_dom_select_data(stack);
@ -944,12 +947,14 @@ dom_select_pop_element(struct dom_stack *stack, struct dom_node *node, void *dat
continue;
}
}
return DOM_CODE_OK;
}
/* For now this is only for matching the ':contains(<string>)' pseudo-class.
* Any node which can contain text and thus characters from the given <string>
* are handled in this common callback. */
static void
enum dom_code
dom_select_push_text(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_select_data *select_data = get_dom_select_data(stack);
@ -961,7 +966,7 @@ dom_select_push_text(struct dom_stack *stack, struct dom_node *node, void *data)
WDBG("Text node: %d chars", node->string.length);
if (!text_sel)
return;
return DOM_CODE_OK;
text = &text_sel->node.string;
@ -973,6 +978,8 @@ dom_select_push_text(struct dom_stack *stack, struct dom_node *node, void *data)
default:
ERROR("Unhandled type");
}
return DOM_CODE_OK;
}
/* Context info for interacting with the DOM tree or stream stack. */
@ -1070,7 +1077,7 @@ select_dom_nodes(struct dom_select *select, struct dom_node *root)
&dom_select_data_context_info);
add_dom_stack_tracer(&select_data.stack, "select-match: ");
if (push_dom_node(&select_data.stack, &select->selector->node)) {
if (push_dom_node(&select_data.stack, &select->selector->node) == DOM_CODE_OK) {
get_dom_stack_top(&select_data.stack)->immutable = 1;
walk_dom_nodes(&stack, root);
}

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../../../.vimrc

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

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../../../.vimrc

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_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_CODE_OK;
}
static enum dom_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_CODE_OK;
}
static enum dom_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_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_CODE_OK;
}
static enum dom_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_CODE_OK;
}
static enum dom_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_CODE_OK;
}
static enum dom_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_CODE_OK;
}
static enum dom_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_CODE_OK;
}
static enum dom_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_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

@ -35,11 +35,16 @@
* information like node subtypes and SGML parser state information. */
static inline struct dom_node *
add_sgml_document(struct dom_stack *stack, struct dom_string *string)
add_sgml_document(struct sgml_parser *parser)
{
struct dom_node *node = init_dom_node(DOM_NODE_DOCUMENT, string);
int allocated = parser->flags & SGML_PARSER_INCREMENTAL;
struct dom_node *node;
return node ? push_dom_node(stack, node) : NULL;
node = init_dom_node(DOM_NODE_DOCUMENT, &parser->uri, allocated);
if (node && push_dom_node(&parser->stack, node) == DOM_CODE_OK)
return node;
return NULL;
}
static inline struct dom_node *
@ -58,7 +63,7 @@ add_sgml_element(struct dom_stack *stack, struct dom_scanner_token *token)
node_info = get_sgml_node_info(parser->info->elements, node);
node->data.element.type = node_info->type;
if (!push_dom_node(stack, node))
if (push_dom_node(stack, node) != DOM_CODE_OK)
return NULL;
state = get_dom_stack_top(stack);
@ -71,7 +76,7 @@ add_sgml_element(struct dom_stack *stack, struct dom_scanner_token *token)
}
static inline void
static inline struct dom_node *
add_sgml_attribute(struct dom_stack *stack,
struct dom_scanner_token *token, struct dom_scanner_token *valtoken)
{
@ -90,12 +95,14 @@ 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))
return;
if (!node || push_dom_node(stack, node) != DOM_CODE_OK)
return NULL;
pop_dom_node(stack);
return node;
}
static inline struct dom_node *
@ -114,33 +121,42 @@ add_sgml_proc_instruction(struct dom_stack *stack, struct dom_scanner_token *tar
node->data.proc_instruction.type = DOM_PROC_INSTRUCTION_XML;
break;
case SGML_TOKEN_PROCESS_XML_STYLESHEET:
node->data.proc_instruction.type = DOM_PROC_INSTRUCTION_XML_STYLESHEET;
break;
case SGML_TOKEN_PROCESS:
default:
node->data.proc_instruction.type = DOM_PROC_INSTRUCTION;
}
return push_dom_node(stack, node);
if (push_dom_node(stack, node) == DOM_CODE_OK)
return node;
return NULL;
}
static inline void
static inline struct dom_node *
add_sgml_node(struct dom_stack *stack, enum dom_node_type type, struct dom_scanner_token *token)
{
struct dom_node *parent = get_dom_stack_top(stack)->node;
struct dom_node *node = add_dom_node(parent, type, &token->string);
if (!node) return;
if (!node) return NULL;
if (token->type == SGML_TOKEN_SPACE)
node->data.text.only_space = 1;
if (push_dom_node(stack, node))
if (push_dom_node(stack, node) == DOM_CODE_OK)
pop_dom_node(stack);
return node;
}
/* SGML parser main handling: */
static enum sgml_parser_code
static enum dom_code
call_sgml_error_function(struct dom_stack *stack, struct dom_scanner_token *token)
{
struct sgml_parser *parser = get_sgml_parser(stack);
@ -151,18 +167,42 @@ call_sgml_error_function(struct dom_stack *stack, struct dom_scanner_token *toke
return parser->error_func(parser, &token->string, line);
}
static inline enum sgml_parser_code
/* Appends to or 'creates' an incomplete token. This can be used to
* force tokens back into the 'stream' if they require that later tokens
* are available.
*
* NOTE: You can only do this for tokens that are not stripped of markup such
* as identifiers. */
static enum dom_code
check_sgml_incomplete(struct dom_scanner *scanner,
struct dom_scanner_token *start,
struct dom_scanner_token *token)
{
if (token && token->type == SGML_TOKEN_INCOMPLETE) {
token->string.length += token->string.string - start->string.string;
token->string.string = start->string.string;
return 1;
} else if (!token && scanner->check_complete && scanner->incomplete) {
size_t left = scanner->end - start->string.string;
assert(left > 0);
token = scanner->current = scanner->table;
scanner->tokens = 1;
token->type = SGML_TOKEN_INCOMPLETE;
set_dom_string(&token->string, start->string.string, left);
return 1;
}
return 0;
}
static inline enum dom_code
parse_sgml_attributes(struct dom_stack *stack, struct dom_scanner *scanner)
{
struct dom_scanner_token name;
assert(dom_scanner_has_tokens(scanner)
&& (get_dom_scanner_token(scanner)->type == SGML_TOKEN_ELEMENT_BEGIN
|| (get_dom_stack_top(stack)->node->type == DOM_NODE_PROCESSING_INSTRUCTION)));
if (get_dom_scanner_token(scanner)->type == SGML_TOKEN_ELEMENT_BEGIN)
skip_dom_scanner_token(scanner);
while (dom_scanner_has_tokens(scanner)) {
struct dom_scanner_token *token = get_dom_scanner_token(scanner);
@ -176,7 +216,7 @@ parse_sgml_attributes(struct dom_stack *stack, struct dom_scanner *scanner)
case SGML_TOKEN_ELEMENT_BEGIN:
case SGML_TOKEN_ELEMENT_END:
case SGML_TOKEN_ELEMENT_EMPTY_END:
return SGML_PARSER_CODE_OK;
return DOM_CODE_OK;
case SGML_TOKEN_IDENT:
copy_struct(&name, token);
@ -188,8 +228,8 @@ parse_sgml_attributes(struct dom_stack *stack, struct dom_scanner *scanner)
/* If the token is not a valid value token
* ignore it. */
token = get_next_dom_scanner_token(scanner);
if (token && token->type == SGML_TOKEN_INCOMPLETE)
return SGML_PARSER_CODE_INCOMPLETE;
if (check_sgml_incomplete(scanner, &name, token))
return DOM_CODE_INCOMPLETE;
if (token
&& token->type != SGML_TOKEN_IDENT
@ -197,14 +237,15 @@ parse_sgml_attributes(struct dom_stack *stack, struct dom_scanner *scanner)
&& token->type != SGML_TOKEN_STRING)
token = NULL;
} else if (token && token->type == SGML_TOKEN_INCOMPLETE) {
return SGML_PARSER_CODE_INCOMPLETE;
} else if (check_sgml_incomplete(scanner, &name, token)) {
return DOM_CODE_INCOMPLETE;
} else {
token = NULL;
}
add_sgml_attribute(stack, &name, token);
if (!add_sgml_attribute(stack, &name, token))
return DOM_CODE_ALLOC_ERR;
/* Skip the value token */
if (token)
@ -212,14 +253,14 @@ parse_sgml_attributes(struct dom_stack *stack, struct dom_scanner *scanner)
break;
case SGML_TOKEN_INCOMPLETE:
return SGML_PARSER_CODE_INCOMPLETE;
return DOM_CODE_INCOMPLETE;
case SGML_TOKEN_ERROR:
{
enum sgml_parser_code code;
enum dom_code code;
code = call_sgml_error_function(stack, token);
if (code != SGML_PARSER_CODE_OK)
if (code != DOM_CODE_OK)
return code;
skip_dom_scanner_token(scanner);
@ -230,10 +271,10 @@ parse_sgml_attributes(struct dom_stack *stack, struct dom_scanner *scanner)
}
}
return SGML_PARSER_CODE_OK;
return DOM_CODE_OK;
}
static enum sgml_parser_code
static enum dom_code
parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
{
struct dom_scanner_token target;
@ -244,21 +285,16 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
switch (token->type) {
case SGML_TOKEN_ELEMENT:
case SGML_TOKEN_ELEMENT_BEGIN:
if (!add_sgml_element(stack, token)) {
if (token->type == SGML_TOKEN_ELEMENT) {
skip_dom_scanner_token(scanner);
break;
}
skip_sgml_tokens(scanner, SGML_TOKEN_TAG_END);
break;
}
if (!add_sgml_element(stack, token))
return DOM_CODE_ALLOC_ERR;
if (token->type == SGML_TOKEN_ELEMENT_BEGIN) {
enum sgml_parser_code code;
enum dom_code code;
skip_dom_scanner_token(scanner);
code = parse_sgml_attributes(stack, scanner);
if (code != SGML_PARSER_CODE_OK)
if (code != DOM_CODE_OK)
return code;
} else {
@ -295,7 +331,8 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
break;
case SGML_TOKEN_NOTATION_COMMENT:
add_sgml_node(stack, DOM_NODE_COMMENT, token);
if (!add_sgml_node(stack, DOM_NODE_COMMENT, token))
return DOM_CODE_ALLOC_ERR;
skip_dom_scanner_token(scanner);
break;
@ -308,7 +345,8 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
break;
case SGML_TOKEN_CDATA_SECTION:
add_sgml_node(stack, DOM_NODE_CDATA_SECTION, token);
if (!add_sgml_node(stack, DOM_NODE_CDATA_SECTION, token))
return DOM_CODE_ALLOC_ERR;
skip_dom_scanner_token(scanner);
break;
@ -320,7 +358,7 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
/* Skip the target token */
token = get_next_dom_scanner_token(scanner);
if (!token || token->type == SGML_TOKEN_INCOMPLETE)
return SGML_PARSER_CODE_INCOMPLETE;
return DOM_CODE_INCOMPLETE;
if (token->type == SGML_TOKEN_ERROR)
break;
@ -328,10 +366,10 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
assert(token->type == SGML_TOKEN_PROCESS_DATA);
/* Fall-through */
case SGML_TOKEN_PROCESS_DATA:
if (add_sgml_proc_instruction(stack, &target, token)
&& (target.type == SGML_TOKEN_PROCESS_XML
|| target.type == SGML_TOKEN_PROCESS_XML_STYLESHEET)
if (!add_sgml_proc_instruction(stack, &target, token))
return DOM_CODE_ALLOC_ERR;
if ((target.type == SGML_TOKEN_PROCESS_XML
|| target.type == SGML_TOKEN_PROCESS_XML_STYLESHEET)
&& token->string.length > 0) {
/* Parse the <?xml data="attributes"?>. */
struct dom_scanner attr_scanner;
@ -361,14 +399,14 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
break;
case SGML_TOKEN_INCOMPLETE:
return SGML_PARSER_CODE_INCOMPLETE;
return DOM_CODE_INCOMPLETE;
case SGML_TOKEN_ERROR:
{
enum sgml_parser_code code;
enum dom_code code;
code = call_sgml_error_function(stack, token);
if (code != SGML_PARSER_CODE_OK)
if (code != DOM_CODE_OK)
return code;
skip_dom_scanner_token(scanner);
@ -382,10 +420,10 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
}
}
return SGML_PARSER_CODE_OK;
return DOM_CODE_OK;
}
enum sgml_parser_code
enum dom_code
parse_sgml(struct sgml_parser *parser, unsigned char *buf, size_t bufsize,
int complete)
{
@ -396,17 +434,15 @@ parse_sgml(struct sgml_parser *parser, unsigned char *buf, size_t bufsize,
parser->flags |= SGML_PARSER_COMPLETE;
if (!parser->root) {
parser->root = add_sgml_document(&parser->stack, &parser->uri);
parser->root = add_sgml_document(parser);
if (!parser->root)
return SGML_PARSER_CODE_MEM_ALLOC;
return DOM_CODE_ALLOC_ERR;
get_dom_stack_top(&parser->stack)->immutable = 1;
}
node = init_dom_node(DOM_NODE_TEXT, &source);
if (!node || !push_dom_node(&parser->parsing, node))
return SGML_PARSER_CODE_MEM_ALLOC;
pop_dom_node(&parser->parsing);
node = init_dom_node(DOM_NODE_TEXT, &source, 0);
if (!node || push_dom_node(&parser->parsing, node) != DOM_CODE_OK)
return DOM_CODE_ALLOC_ERR;
return parser->code;
}
@ -423,10 +459,12 @@ parse_sgml(struct sgml_parser *parser, unsigned char *buf, size_t bufsize,
struct sgml_parsing_state {
struct dom_scanner scanner;
struct dom_node *node;
struct dom_string incomplete;
size_t depth;
unsigned int resume:1;
};
static void
enum dom_code
sgml_parsing_push(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct sgml_parser *parser = get_sgml_parser(stack);
@ -435,29 +473,109 @@ sgml_parsing_push(struct dom_stack *stack, struct dom_node *node, void *data)
int complete = !!(parser->flags & SGML_PARSER_COMPLETE);
int incremental = !!(parser->flags & SGML_PARSER_INCREMENTAL);
int detect_errors = !!(parser->flags & SGML_PARSER_DETECT_ERRORS);
struct dom_string *string = &node->string;
struct dom_scanner_token *token;
struct dom_string incomplete;
enum sgml_scanner_state scanner_state = SGML_STATE_TEXT;
parsing->depth = parser->stack.depth;
get_dom_stack_top(&parser->stack)->immutable = 1;
init_dom_scanner(&parsing->scanner, &sgml_scanner_info, &node->string,
SGML_STATE_TEXT, count_lines, complete, incremental,
if (stack->depth > 1) {
struct sgml_parsing_state *parent = &parsing[-1];
if (parent->resume) {
if (is_dom_string_set(&parent->incomplete)) {
if (!add_to_dom_string(&parent->incomplete,
string->string,
string->length)) {
parser->code = DOM_CODE_ALLOC_ERR;
return DOM_CODE_OK;
}
string = &parent->incomplete;
}
scanner_state = parent->scanner.state;
/* Pop down to the parent. */
parsing = parent;
parsing->resume = 0;
pop_dom_node(stack);
}
}
init_dom_scanner(&parsing->scanner, &sgml_scanner_info, string,
scanner_state, count_lines, complete, incremental,
detect_errors);
parser->code = parse_sgml_plain(&parser->stack, &parsing->scanner);
if (scanner_state == SGML_STATE_ELEMENT) {
parser->code = parse_sgml_attributes(&parser->stack, &parsing->scanner);
if (parser->code == DOM_CODE_OK)
parser->code = parse_sgml_plain(&parser->stack, &parsing->scanner);
} else {
parser->code = parse_sgml_plain(&parser->stack, &parsing->scanner);
}
if (complete) {
pop_dom_node(&parser->parsing);
return DOM_CODE_OK;
}
if (parser->code != DOM_CODE_INCOMPLETE) {
/* No need to preserve the default scanner state. */
if (parsing->scanner.state == SGML_STATE_TEXT) {
pop_dom_node(&parser->parsing);
return DOM_CODE_OK;
}
done_dom_string(&parsing->incomplete);
parsing->resume = 1;
return DOM_CODE_OK;
}
token = get_dom_scanner_token(&parsing->scanner);
assert(token && token->type == SGML_TOKEN_INCOMPLETE);
string = &token->string;
set_dom_string(&incomplete, NULL, 0);
if (!init_dom_string(&incomplete, string->string, string->length)) {
parser->code = DOM_CODE_ALLOC_ERR;
return DOM_CODE_OK;
}
done_dom_string(&parsing->incomplete);
set_dom_string(&parsing->incomplete, incomplete.string, incomplete.length);
parsing->resume = 1;
return DOM_CODE_OK;
}
static void
enum dom_code
sgml_parsing_pop(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct sgml_parser *parser = get_sgml_parser(stack);
struct sgml_parsing_state *parsing = data;
/* Pop the stack back to the state it was in. This includes cleaning
* away even immutable states left on the stack. */
while (parsing->depth < parser->stack.depth) {
get_dom_stack_top(&parser->stack)->immutable = 0;
pop_dom_node(&parser->stack);
/* Only clean up the stack if complete so that we get proper nesting. */
if (parser->flags & SGML_PARSER_COMPLETE) {
/* Pop the stack back to the state it was in. This includes cleaning
* away even immutable states left on the stack. */
while (parsing->depth < parser->stack.depth) {
get_dom_stack_top(&parser->stack)->immutable = 0;
pop_dom_node(&parser->stack);
}
/* It's bigger than when calling done_sgml_parser() in the middle of an
* incomplete parsing. */
assert(parsing->depth >= parser->stack.depth);
}
assert(parsing->depth == parser->stack.depth);
done_dom_string(&parsing->incomplete);
return DOM_CODE_OK;
}
static struct dom_stack_context_info sgml_parsing_context_info = {
@ -601,8 +719,10 @@ init_sgml_parser(enum sgml_parser_type type, enum sgml_document_type doctype,
void
done_sgml_parser(struct sgml_parser *parser)
{
done_dom_stack(&parser->stack);
while (!dom_stack_is_empty(&parser->parsing))
pop_dom_node(&parser->parsing);
done_dom_stack(&parser->parsing);
done_dom_stack(&parser->stack);
done_dom_string(&parser->uri);
mem_free(parser);
}

View File

@ -2,6 +2,7 @@
#ifndef EL_DOM_SGML_PARSER_H
#define EL_DOM_SGML_PARSER_H
#include "dom/code.h"
#include "dom/node.h"
#include "dom/stack.h"
#include "dom/sgml/sgml.h"
@ -62,27 +63,13 @@ struct sgml_parser_state {
struct dom_scanner_token end_token;
};
/** (Error) codes for the SGML parser
*
* These enum values are used for return codes.
*/
enum sgml_parser_code {
SGML_PARSER_CODE_OK, /*: The parsing was successful */
SGML_PARSER_CODE_INCOMPLETE, /*: The parsing could not be completed */
SGML_PARSER_CODE_MEM_ALLOC, /*: Failed to allocate memory */
/**
* FIXME: For when we will add support for requiring stricter parsing
* or even a validator. */
SGML_PARSER_CODE_ERROR,
};
/** SGML error callback
*
* Called by the SGML parser when a parsing error has occurred.
*
* If the return code is not ref:[SGML_PARSER_CODE_OK] the parsing will be
* If the return code is not ref:[DOM_CODE_OK] the parsing will be
* ended and that code will be returned. */
typedef enum sgml_parser_code
typedef enum dom_code
(*sgml_error_T)(struct sgml_parser *, struct dom_string *, unsigned int);
@ -101,7 +88,7 @@ struct sgml_parser {
struct dom_string uri; /*: The URI of the DOM document */
struct dom_node *root; /*: The document root node */
enum sgml_parser_code code; /*: The latest (error) code */
enum dom_code code; /*: The latest (error) code */
sgml_error_T error_func; /*: Called for detected errors */
struct dom_stack stack; /*: A stack for tracking parsed nodes */
@ -142,10 +129,10 @@ void done_sgml_parser(struct sgml_parser *parser);
* bufsize:: The size of the buffer given in the buf parameter.
* complete:: Whether this is the last chunk to parse.
*
* The returned code is ref:[SGML_PARSER_CODE_OK] if the buffer was
* The returned code is ref:[DOM_CODE_OK] if the buffer was
* successfully parserd, else a code hinting at the error.
*/
enum sgml_parser_code
enum dom_code
parse_sgml(struct sgml_parser *parser, unsigned char *buf, size_t bufsize, int complete);
/** Get the line position in the source

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),
@ -368,12 +368,20 @@ skip_sgml_comment(struct dom_scanner *scanner, unsigned char **string,
/* It is always safe to access index -2 and -1 here since we
* are supposed to have '<!--' before this is called. We do
* however need to check that the '-->' are not overlapping any
* preceeding '-'. */
if (pos[-2] == '-' && pos[-1] == '-' && &pos[-2] >= *string) {
length = pos - *string - 2;
*possibly_incomplete = 0;
pos++;
break;
* preceeding '-'. Additionally also handle the quirky '--!>'
* end sometimes found. */
if (pos[-2] == '-') {
if (pos[-1] == '-' && &pos[-2] >= *string) {
length = pos - *string - 2;
*possibly_incomplete = 0;
pos++;
break;
} else if (pos[-1] == '!' && pos[-3] == '-' && &pos[-3] >= *string) {
length = pos - *string - 3;
*possibly_incomplete = 0;
pos++;
break;
}
}
}
@ -431,6 +439,7 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
enum sgml_token_type type = SGML_TOKEN_GARBAGE;
int real_length = -1;
int possibly_incomplete = 1;
enum sgml_scanner_state scanner_state = scanner->state;
token->string.string = string++;
@ -440,13 +449,17 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
if (scanner->state == SGML_STATE_ELEMENT) {
/* Already inside an element so insert a tag end token
* and continue scanning in next iteration. */
string--;
real_length = 0;
type = SGML_TOKEN_TAG_END;
scanner->state = SGML_STATE_TEXT;
scanner_state = SGML_STATE_TEXT;
/* We are creating a 'virtual' that has no source. */
possibly_incomplete = 0;
string = token->string.string;
real_length = 0;
} else if (string == scanner->end) {
/* It is incomplete so prevent out of bound acess to
* the scanned string. */
} else if (is_sgml_ident(*string)) {
token->string.string = string;
@ -455,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++;
@ -468,8 +481,8 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
/* We found the end. */
possibly_incomplete = 0;
}
scanner->state = SGML_STATE_ELEMENT;
type = SGML_TOKEN_ELEMENT_BEGIN;
scanner_state = SGML_STATE_ELEMENT;
}
} else if (*string == '!') {
@ -519,7 +532,7 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
type = map_dom_scanner_string(scanner, pos, string, base);
scanner->state = SGML_STATE_PROC_INST;
scanner_state = SGML_STATE_PROC_INST;
real_length = string - token->string.string;
skip_sgml_space(scanner, &string);
@ -531,11 +544,37 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
possibly_incomplete = 0;
}
if (scanner->check_complete && scanner->incomplete) {
/* We need to fit both the process target token
* and the process data token into the scanner
* table. */
if (token + 1 >= scanner->table + DOM_SCANNER_TOKENS) {
possibly_incomplete = 1;
} else if (!possibly_incomplete) {
/* FIXME: We do this twice. */
for (pos = string + 1;
(pos = skip_sgml_chars(scanner, pos, '>'));
pos++) {
if (pos[-1] == '?')
break;
}
if (!pos)
possibly_incomplete = 1;
}
if (possibly_incomplete)
string = scanner->end;
}
} else if (*string == '/') {
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;
@ -555,8 +594,9 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
possibly_incomplete = 0;
}
if (type != SGML_TOKEN_GARBAGE)
scanner->state = SGML_STATE_TEXT;
if (type != SGML_TOKEN_GARBAGE) {
scanner_state = SGML_STATE_TEXT;
}
} else {
/* Alien < > stuff so ignore it */
@ -586,7 +626,7 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
type = SGML_TOKEN_TAG_END;
assert(scanner->state == SGML_STATE_ELEMENT);
scanner->state = SGML_STATE_TEXT;
scanner_state = SGML_STATE_TEXT;
} else if (first_char == '/') {
/* We allow '/' inside elements and only consider it as an end
@ -598,12 +638,15 @@ 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;
assert(scanner->state == SGML_STATE_ELEMENT);
scanner->state = SGML_STATE_TEXT;
scanner_state = SGML_STATE_TEXT;
/* We found the end. */
possibly_incomplete = 0;
@ -631,7 +674,12 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
/* We found the end. */
possibly_incomplete = 0;
} else if (is_sgml_attribute(*string)) {
} else if (scanner->check_complete && scanner->incomplete) {
/* Force an incomplete token. */
string = scanner->end;
} else if (string < scanner->end
&& is_sgml_attribute(*string)) {
token->string.string++;
scan_sgml_attribute(scanner, string);
type = SGML_TOKEN_ATTRIBUTE;
@ -643,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] == '>') {
@ -670,6 +719,10 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
}
}
/* Only apply the state change if the token was not abandoned because
* it was incomplete. */
scanner->state = scanner_state;
token->type = type;
token->string.length = real_length >= 0 ? real_length : string - token->string.string;
token->precedence = get_sgml_precedence(type);
@ -684,9 +737,9 @@ scan_sgml_proc_inst_token(struct dom_scanner *scanner, struct dom_scanner_token
{
unsigned char *string = scanner->position;
/* The length can be empty for '<??>'. */
size_t length = -1;
ssize_t length = -1;
token->string.string = string;
token->string.string = string++;
/* Figure out where the processing instruction ends. This doesn't use
* skip_sgml() since we MUST ignore precedence here to allow '<' inside

View File

@ -4,7 +4,7 @@
#include <stdlib.h>
#include "dom/stack.h"
#include "dom/node.h"
#include "dom/string.h"
/* The flags stored in the attribute sgml node info data */
@ -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

@ -129,10 +129,12 @@ enum dom_stack_action {
DOM_STACK_POP,
};
static void
/* Returns whether the node should be freed with done_dom_node(). */
static int
call_dom_stack_callbacks(struct dom_stack *stack, struct dom_stack_state *state,
enum dom_stack_action action)
{
int free_node = 0;
int i;
for (i = 0; i < stack->contexts_size; i++) {
@ -148,13 +150,21 @@ call_dom_stack_callbacks(struct dom_stack *stack, struct dom_stack_state *state,
void *data = get_dom_stack_state_data(context, state);
stack->current = context;
callback(stack, state->node, data);
switch (callback(stack, state->node, data)) {
case DOM_CODE_FREE_NODE:
free_node = 1;
break;
default:
break;
}
stack->current = NULL;
}
}
return free_node;
}
struct dom_node *
enum dom_code
push_dom_node(struct dom_stack *stack, struct dom_node *node)
{
struct dom_stack_state *state;
@ -164,13 +174,13 @@ push_dom_node(struct dom_stack *stack, struct dom_node *node)
assert(0 < node->type && node->type < DOM_NODES);
if (stack->depth > DOM_STACK_MAX_DEPTH) {
return NULL;
return DOM_CODE_MAX_DEPTH_ERR;
}
state = realloc_dom_stack_states(&stack->states, stack->depth);
if (!state) {
done_dom_node(node);
return NULL;
return DOM_CODE_ALLOC_ERR;
}
state += stack->depth;
@ -181,7 +191,7 @@ push_dom_node(struct dom_stack *stack, struct dom_node *node)
if (context->info->object_size
&& !realloc_dom_stack_state_objects(context, stack->depth)) {
done_dom_node(node);
return NULL;
return DOM_CODE_ALLOC_ERR;
}
}
@ -193,7 +203,7 @@ push_dom_node(struct dom_stack *stack, struct dom_node *node)
stack->depth++;
call_dom_stack_callbacks(stack, state, DOM_STACK_PUSH);
return node;
return DOM_CODE_OK;
}
void
@ -211,9 +221,8 @@ pop_dom_node(struct dom_stack *stack)
if (state->immutable)
return;
call_dom_stack_callbacks(stack, state, DOM_STACK_POP);
if (stack->flags & DOM_STACK_FLAG_FREE_NODES)
if (call_dom_stack_callbacks(stack, state, DOM_STACK_POP)
|| (stack->flags & DOM_STACK_FLAG_FREE_NODES))
done_dom_node(state->node);
stack->depth--;
@ -349,7 +358,8 @@ walk_dom_nodes(struct dom_stack *stack, struct dom_node *root)
if (!context)
return;
push_dom_node(stack, root);
if (push_dom_node(stack, root) != DOM_CODE_OK)
return;
while (!dom_stack_is_empty(stack)) {
struct dom_stack_state *state = get_dom_stack_top(stack);
@ -410,7 +420,7 @@ walk_dom_nodes(struct dom_stack *stack, struct dom_node *root)
if (is_dom_node_list_member(list, wstate->index)) {
struct dom_node *child = list->entries[wstate->index++];
if (push_dom_node(stack, child))
if (push_dom_node(stack, child) == DOM_CODE_OK)
continue;
}
@ -488,7 +498,7 @@ static unsigned char indent_string[] =
#define get_indent_offset(stack) \
((stack)->depth < sizeof(indent_string)/2 ? (stack)->depth * 2 : sizeof(indent_string))
static void
enum dom_code
dom_stack_trace_tree(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_string *value = &node->string;
@ -499,9 +509,11 @@ dom_stack_trace_tree(struct dom_stack *stack, struct dom_node *node, void *data)
get_indent_offset(stack), indent_string,
name->length, name->string,
value->length, value->string);
return DOM_CODE_OK;
}
static void
enum dom_code
dom_stack_trace_id_leaf(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_string value;
@ -520,11 +532,12 @@ dom_stack_trace_id_leaf(struct dom_stack *stack, struct dom_node *node, void *da
id->length, id->string, name->length, name->string,
value.length, value.string);
if (is_dom_string_set(&value))
done_dom_string(&value);
done_dom_string(&value);
return DOM_CODE_OK;
}
static void
enum dom_code
dom_stack_trace_leaf(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_string *name;
@ -541,11 +554,12 @@ dom_stack_trace_leaf(struct dom_stack *stack, struct dom_node *node, void *data)
name->length, name->string,
value.length, value.string);
if (is_dom_string_set(&value))
done_dom_string(&value);
done_dom_string(&value);
return DOM_CODE_OK;
}
static void
enum dom_code
dom_stack_trace_branch(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_string *name;
@ -560,6 +574,8 @@ dom_stack_trace_branch(struct dom_stack *stack, struct dom_node *node, void *dat
empty_string_or_(stack->current->data),
get_indent_offset(stack), indent_string,
id->length, id->string, name->length, name->string);
return DOM_CODE_OK;
}
struct dom_stack_context_info dom_stack_trace_context_info = {

View File

@ -1,6 +1,7 @@
#ifndef EL_DOM_STACK_H
#define EL_DOM_STACK_H
#include "dom/code.h"
#include "dom/node.h"
#include "util/error.h"
#include "util/hash.h"
@ -12,7 +13,8 @@ struct dom_stack;
/** DOM stack callback
*
* Used by contexts, for 'hooking' into the node traversing. */
typedef void (*dom_stack_callback_T)(struct dom_stack *, struct dom_node *, void *);
typedef enum dom_code
(*dom_stack_callback_T)(struct dom_stack *, struct dom_node *, void *);
#define DOM_STACK_MAX_DEPTH 4096
@ -230,7 +232,7 @@ void done_dom_stack_context(struct dom_stack *stack, struct dom_stack_context *c
*
* If an error occurs the node is released with ref:[done_dom_node] and NULL is
* returned. Else the pushed node is returned. */
struct dom_node *push_dom_node(struct dom_stack *stack, struct dom_node *node);
enum dom_code push_dom_node(struct dom_stack *stack, struct dom_node *node);
/** Pop the top stack state
*

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)

3
src/dom/test/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
html-mangle
sgml-parser
trash

View File

@ -1,2 +0,0 @@
:set runtimepath+=.
:runtime ../../../.vimrc

View File

@ -4,6 +4,7 @@ include $(top_builddir)/Makefile.config
# Disabled since it requires DOM_STACK_TRACE to be defined
# dom-select
TEST_PROGS = \
html-mangle \
sgml-parser
TESTDEPS = \

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++) {

221
src/dom/test/html-mangle.c Normal file
View File

@ -0,0 +1,221 @@
/* HTML manglizer
* --------------
* Copyright (C) 2004 by Michal Zalewski <lcamtuf@coredump.cx>
*
* Based on mangleme-1.2, downloaded on the date below.
*
* Date: Tue, 31 Jan 2006 10:14:38 +0100 (CET)
* From: Michal Zalewski <lcamtuf@dione.ids.pl>
* To: Jonas Fonseca <fonseca@diku.dk>
* Subject: Re: [mangleme] Question about license and reusability
* In-Reply-To: <20060131022616.GB30744@diku.dk>
* Message-ID: <Pine.LNX.4.58.0601311013400.24339@dione>
*
* On Tue, 31 Jan 2006, Jonas Fonseca wrote:
* > I would like to reuse your HTML manglizer for stress testing a program I
* > am working on (licensed under GPL) but mangleme.tgz (version 1.2)
* > doesn't carry any license info as far as I can see. The freshmeat
* > project page mentions LGPL, is that authoritative?
*
* The program is so trivial I have no issues with other people using it
* under any licence they choose, to be honest. Consider it to be freeware,
* or LGPL if you insist on having some restrictions ;-)
*
* In other words, go ahead.
*
* Cheers,
* /mz
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define R(x) (rand() % (x))
#define MAXTCOUNT 100
#define MAXPCOUNT 20
#define MAXSTR2 80
#define MAXTAGS 80
#define MAXPARS 20
/* Tag and parameter list: guesstimating / reference compilation. */
static char* tags[MAXTAGS][MAXPARS] = {
{ "A", "NAME", "HREF", "REF", "REV", "TITLE", "TARGET", "SHAPE", "onLoad", "STYLE", 0 },
{ "APPLET", "CODEBASE", "CODE", "NAME", "ALIGN", "ALT", "HEIGHT", "WIDTH", "HSPACE", "VSPACE", "DOWNLOAD", "HEIGHT", "NAME", "TITLE", "onLoad", "STYLE", 0 },
{ "AREA", "SHAPE", "ALT", "CO-ORDS", "HREF", "onLoad", "STYLE", 0 },
{ "B", "onLoad", "STYLE", 0 },
{ "BANNER", "onLoad", "STYLE", 0 },
{ "BASE", "HREF", "TARGET", "onLoad", "STYLE", 0 },
{ "BASEFONT", "SIZE", "onLoad", "STYLE", 0 },
{ "BGSOUND", "SRC", "LOOP", "onLoad", "STYLE", 0 },
{ "BQ", "CLEAR", "NOWRAP", "onLoad", "STYLE", 0 },
{ "BODY", "BACKGROUND", "BGCOLOR", "TEXT", "LINK", "ALINK", "VLINK", "LEFTMARGIN", "TOPMARGIN", "BGPROPERTIES", "onLoad", "STYLE", 0 },
{ "CAPTION", "ALIGN", "VALIGN", "onLoad", "STYLE", 0 },
{ "CENTER", "onLoad", "STYLE", 0 },
{ "COL", "ALIGN", "SPAN", "onLoad", "STYLE", 0 },
{ "COLGROUP", "ALIGN", "VALIGN", "HALIGN", "WIDTH", "SPAN", "onLoad", "STYLE", 0 },
{ "DIV", "ALIGN", "CLASS", "LANG", "onLoad", "STYLE", 0 },
{ "EMBED", "SRC", "HEIGHT", "WIDTH", "UNITS", "NAME", "PALETTE", "onLoad", "STYLE", 0 },
{ "FIG", "SRC", "ALIGN", "HEIGHT", "WIDTH", "UNITS", "IMAGEMAP", "onLoad", "STYLE", 0 },
{ "FN", "ID", "onLoad", "STYLE", 0 },
{ "FONT", "SIZE", "COLOR", "FACE", "onLoad", "STYLE", 0 },
{ "FORM", "ACTION", "METHOD", "ENCTYPE", "TARGET", "SCRIPT", "onLoad", "STYLE", 0 },
{ "FRAME", "SRC", "NAME", "MARGINWIDTH", "MARGINHEIGHT", "SCROLLING", "FRAMESPACING", "onLoad", "STYLE", 0 },
{ "FRAMESET", "ROWS", "COLS", "onLoad", "STYLE", 0 },
{ "H1", "SRC", "DINGBAT", "onLoad", "STYLE", 0 },
{ "HEAD", "onLoad", "STYLE", 0 },
{ "HR", "SRC", "SIZE", "WIDTH", "ALIGN", "COLOR", "onLoad", "STYLE", 0 },
{ "HTML", "onLoad", "STYLE", 0 },
{ "IFRAME", "ALIGN", "FRAMEBORDER", "HEIGHT", "MARGINHEIGHT", "MARGINWIDTH", "NAME", "SCROLLING", "SRC", "ADDRESS", "WIDTH", "onLoad", "STYLE", 0 },
{ "IMG", "ALIGN", "ALT", "SRC", "BORDER", "DYNSRC", "HEIGHT", "HSPACE", "ISMAP", "LOOP", "LOWSRC", "START", "UNITS", "USEMAP", "WIDTH", "VSPACE", "onLoad", "STYLE", 0 },
{ "INPUT", "TYPE", "NAME", "VALUE", "onLoad", "STYLE", 0 },
{ "ISINDEX", "HREF", "PROMPT", "onLoad", "STYLE", 0 },
{ "LI", "SRC", "DINGBAT", "SKIP", "TYPE", "VALUE", "onLoad", "STYLE", 0 },
{ "LINK", "REL", "REV", "HREF", "TITLE", "onLoad", "STYLE", 0 },
{ "MAP", "NAME", "onLoad", "STYLE", 0 },
{ "MARQUEE", "ALIGN", "BEHAVIOR", "BGCOLOR", "DIRECTION", "HEIGHT", "HSPACE", "LOOP", "SCROLLAMOUNT", "SCROLLDELAY", "WIDTH", "VSPACE", "onLoad", "STYLE", 0 },
{ "MENU", "onLoad", "STYLE", 0 },
{ "META", "HTTP-EQUIV", "CONTENT", "NAME", "onLoad", "STYLE", 0 },
{ "MULTICOL", "COLS", "GUTTER", "WIDTH", "onLoad", "STYLE", 0 },
{ "NOFRAMES", "onLoad", "STYLE", 0 },
{ "NOTE", "CLASS", "SRC", "onLoad", "STYLE", 0 },
{ "OVERLAY", "SRC", "X", "Y", "HEIGHT", "WIDTH", "UNITS", "IMAGEMAP", "onLoad", "STYLE", 0 },
{ "PARAM", "NAME", "VALUE", "onLoad", "STYLE", 0 },
{ "RANGE", "FROM", "UNTIL", "onLoad", "STYLE", 0 },
{ "SCRIPT", "LANGUAGE", "onLoad", "STYLE", 0 },
{ "SELECT", "NAME", "SIZE", "MULTIPLE", "WIDTH", "HEIGHT", "UNITS", "onLoad", "STYLE", 0 },
{ "OPTION", "VALUE", "SHAPE", "onLoad", "STYLE", 0 },
{ "SPACER", "TYPE", "SIZE", "WIDTH", "HEIGHT", "ALIGN", "onLoad", "STYLE", 0 },
{ "SPOT", "ID", "onLoad", "STYLE", 0 },
{ "TAB", "INDENT", "TO", "ALIGN", "DP", "onLoad", "STYLE", 0 },
{ "TABLE", "ALIGN", "WIDTH", "BORDER", "CELLPADDING", "CELLSPACING", "BGCOLOR", "VALIGN", "COLSPEC", "UNITS", "DP", "onLoad", "STYLE", 0 },
{ "TBODY", "CLASS", "ID", "onLoad", "STYLE", 0 },
{ "TD", "COLSPAN", "ROWSPAN", "ALIGN", "VALIGN", "BGCOLOR", "onLoad", "STYLE", 0 },
{ "TEXTAREA", "NAME", "COLS", "ROWS", "onLoad", "STYLE", 0 },
{ "TEXTFLOW", "CLASS", "ID", "onLoad", "STYLE", 0 },
{ "TFOOT", "COLSPAN", "ROWSPAN", "ALIGN", "VALIGN", "BGCOLOR", "onLoad", "STYLE", 0 },
{ "TH", "ALIGN", "CLASS", "ID", "onLoad", "STYLE", 0 },
{ "TITLE", "onLoad", "STYLE", 0 },
{ "TR", "ALIGN", "VALIGN", "BGCOLOR", "CLASS", "onLoad", "STYLE", 0 },
{ "UL", "SRC", "DINGBAT", "WRAP", "TYPE", "PLAIN", "onLoad", "STYLE", 0 },
{ 0 }
};
void make_up_value(void)
{
char c=R(2);
if (c) putchar('"');
switch (R(31)) {
case 0: printf("javascript:"); make_up_value(); break;
#if 0
case 1: printf("jar:"); make_up_value(); break;
#endif
case 2: printf("mk:"); make_up_value(); break;
case 3: printf("file:"); make_up_value(); break;
case 4: printf("http:"); make_up_value(); break;
case 5: printf("about:"); make_up_value(); break;
case 6: printf("_blank"); break;
case 7: printf("_self"); break;
case 8: printf("top"); break;
case 9: printf("left"); break;
case 10: putchar('&'); make_up_value(); putchar(';'); break;
case 11: make_up_value(); make_up_value(); break;
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19:
case 20:
{
int c = R(10) ? R(10) : (1 + R(MAXSTR2) * R(MAXSTR2));
char *x = malloc(c);
memset(x,R(256),c);
fwrite(x,c,1,stdout);
free(x);
break;
}
case 21: printf("%s","%n%n%n%n%n%n"); break;
case 22: putchar('#'); break;
case 23: putchar('*'); break;
default:
if (R(2)) putchar('-'); printf("%d",rand());
break;
}
if (c) putchar('"');
}
void random_tag(void)
{
int tn, tc;
do
tn = R(MAXTAGS);
while (!tags[tn][0]);
tc = R(MAXPCOUNT) + 1;
putchar('<');
switch (R(10)) {
case 0: putchar(R(256)); break;
case 1: putchar('/');
}
printf("%s", tags[tn][0]);
while (tc--) {
int pn;
switch (R(32)) {
case 0: putchar(R(256));
case 1: break;
default: putchar(' ');
}
do
pn = R(MAXPARS-1) + 1;
while (!tags[tn][pn]);
printf("%s", tags[tn][pn]);
switch (R(32)) {
case 0: putchar(R(256));
case 1: break;
default: putchar('=');
}
make_up_value();
}
putchar('>');
}
int main(int argc, char **argv)
{
int tc, seed;
printf("<HTML>\n");
printf("<HEAD>\n");
seed = (time(0) ^ (getpid() << 16));
#if 0
fprintf(stderr,"[%u] Mangle attempt 0x%08x (%s) -- %s\n", (int)time(0), seed, getenv("HTTP_USER_AGENT"), getenv("REMOTE_ADDR"));
#endif
srand(seed);
tc = R(MAXTCOUNT) + 1;
while (tc--) random_tag();
fflush(0);
return 0;
}

View File

@ -11,7 +11,9 @@
#include "elinks.h"
#include "dom/configuration.h"
#include "dom/node.h"
#include "dom/sgml/dump.h"
#include "dom/sgml/parser.h"
#include "dom/stack.h"
@ -97,7 +99,7 @@ print_indent(struct dom_stack *stack)
printf("%.*s", get_indent_offset(stack), indent_string);
}
static void
static enum dom_code
sgml_parser_test_tree(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_string *value = &node->string;
@ -105,15 +107,17 @@ sgml_parser_test_tree(struct dom_stack *stack, struct dom_node *node, void *data
/* Always print the URI for identification. */
if (update_number_of_lines(stack))
return;
return DOM_CODE_OK;
print_indent(stack);
printf("%.*s: %.*s\n",
name->length, name->string,
value->length, value->string);
return DOM_CODE_OK;
}
static void
static enum dom_code
sgml_parser_test_id_leaf(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_string *name;
@ -122,7 +126,7 @@ sgml_parser_test_id_leaf(struct dom_stack *stack, struct dom_node *node, void *d
assert(node);
if (update_number_of_lines(stack))
return;
return DOM_CODE_OK;
name = get_dom_node_name(node);
id = get_dom_node_type_name(node->type);
@ -133,9 +137,11 @@ sgml_parser_test_id_leaf(struct dom_stack *stack, struct dom_node *node, void *d
name->length, name->string);
print_dom_node_value(node);
printf("\n");
return DOM_CODE_OK;
}
static void
static enum dom_code
sgml_parser_test_leaf(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_string *name;
@ -143,7 +149,7 @@ sgml_parser_test_leaf(struct dom_stack *stack, struct dom_node *node, void *data
assert(node);
if (update_number_of_lines(stack))
return;
return DOM_CODE_OK;
name = get_dom_node_name(node);
@ -152,9 +158,11 @@ sgml_parser_test_leaf(struct dom_stack *stack, struct dom_node *node, void *data
name->length, name->string);
print_dom_node_value(node);
printf("\n");
return DOM_CODE_OK;
}
static void
static enum dom_code
sgml_parser_test_branch(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct dom_string *name;
@ -163,7 +171,7 @@ sgml_parser_test_branch(struct dom_stack *stack, struct dom_node *node, void *da
assert(node);
if (update_number_of_lines(stack))
return;
return DOM_CODE_OK;
name = get_dom_node_name(node);
id = get_dom_node_type_name(node->type);
@ -171,9 +179,11 @@ sgml_parser_test_branch(struct dom_stack *stack, struct dom_node *node, void *da
print_indent(stack);
printf("%.*s: %.*s\n",
id->length, id->string, name->length, name->string);
return DOM_CODE_OK;
}
static void
static enum dom_code
sgml_parser_test_end(struct dom_stack *stack, struct dom_node *node, void *data)
{
struct sgml_parser *parser = stack->contexts[0]->data;
@ -182,6 +192,8 @@ sgml_parser_test_end(struct dom_stack *stack, struct dom_node *node, void *data)
&& !(parser->flags & SGML_PARSER_DETECT_ERRORS)) {
printf("%d\n", number_of_lines);
}
return DOM_CODE_OK;
}
struct dom_stack_context_info sgml_parser_test_context_info = {
@ -220,14 +232,14 @@ struct dom_stack_context_info sgml_parser_test_context_info = {
}
};
static enum sgml_parser_code
static enum dom_code
sgml_error_function(struct sgml_parser *parser, struct dom_string *string,
unsigned int line_number)
{
printf("error on line %d: %.*s\n",
line_number, string->length, string->string);
return SGML_PARSER_CODE_OK;
return DOM_CODE_OK;
}
void die(const char *msg, ...)
@ -250,10 +262,15 @@ main(int argc, char *argv[])
struct sgml_parser *parser;
enum sgml_document_type doctype = SGML_DOCTYPE_HTML;
enum sgml_parser_flag flags = 0;
enum sgml_parser_code code = 0;
enum sgml_parser_type type = SGML_PARSER_STREAM;
enum dom_code code = 0;
enum dom_config_flag normalize_flags = 0;
int normalize = 0;
int dump = 0;
int complete = 1;
struct dom_string uri = INIT_DOM_STRING("dom://test", -1);
struct dom_string source = INIT_DOM_STRING("(no source)", -1);
size_t read_stdin = 0;
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++) {
@ -288,6 +305,34 @@ main(int argc, char *argv[])
set_dom_string(&source, argv[i], strlen(argv[i]));
}
} else if (!strncmp(arg, "stdin", 5)) {
arg += 5;
if (*arg == '=') {
arg++;
read_stdin = atoi(arg);
set_dom_string(&source, arg, strlen(arg));
} else {
i++;
if (i >= argc)
die("--stdin expects a number");
read_stdin = atoi(argv[i]);
}
flags |= SGML_PARSER_INCREMENTAL;
} else if (!strncmp(arg, "normalize", 9)) {
arg += 9;
if (*arg == '=') {
arg++;
} else {
i++;
if (i >= argc)
die("--normalize expects a string");
arg = argv[i];
}
normalize = 1;
normalize_flags = parse_dom_config(arg, ',');
type = SGML_PARSER_TREE;
} else if (!strcmp(arg, "print-lines")) {
flags |= SGML_PARSER_COUNT_LINES;
@ -295,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;
@ -306,27 +355,83 @@ main(int argc, char *argv[])
}
}
parser = init_sgml_parser(SGML_PARSER_STREAM, doctype, &uri, flags);
parser = init_sgml_parser(type, doctype, &uri, flags);
if (!parser) return 1;
parser->error_func = sgml_error_function;
add_dom_stack_context(&parser->stack, NULL, &sgml_parser_test_context_info);
if (normalize)
add_dom_config_normalizer(&parser->stack, normalize_flags);
else if (!dump)
add_dom_stack_context(&parser->stack, NULL, &sgml_parser_test_context_info);
if (read_stdin > 0) {
unsigned char *buffer;
buffer = mem_alloc(read_stdin);
if (!buffer)
die("Cannot allocate buffer");
complete = 0;
while (!complete) {
size_t size = fread(buffer, 1, read_stdin, stdin);
if (ferror(stdin))
die("error reading from stdin");
complete = feof(stdin);
code = parse_sgml(parser, buffer, size, complete);
switch (code) {
case DOM_CODE_OK:
break;
case DOM_CODE_INCOMPLETE:
if (!complete) break;
/* Error */
default:
complete = 1;
}
}
mem_free(buffer);
} else {
code = parse_sgml(parser, source.string, source.length, complete);
}
code = parse_sgml(parser, source.string, source.length, complete);
if (parser->root) {
size_t root_offset = parser->stack.depth - 1;
assert(!complete || parser->stack.depth > 0);
assert(!complete || root_offset == 0);
get_dom_stack_state(&parser->stack, root_offset)->immutable = 0;
/* For SGML_PARSER_STREAM this will free the DOM
* root node. */
while (!dom_stack_is_empty(&parser->stack))
while (!dom_stack_is_empty(&parser->stack)) {
get_dom_stack_top(&parser->stack)->immutable = 0;
pop_dom_node(&parser->stack);
}
if (normalize || dump) {
struct dom_stack stack;
/* Note, that we cannot free nodes when walking the DOM
* tree since walk_dom_node() uses an index to traverse
* the tree. */
init_dom_stack(&stack, DOM_STACK_FLAG_NONE);
/* XXX: This context needs to be added first because it
* assumes the parser can be accessed via
* stack->contexts[0].data. */
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);
}
}
done_sgml_parser(parser);
#ifdef DEBUG_MEMLEAK
check_memory_leaks();
#endif
return code;
return code != DOM_CODE_OK ? 1 : 0;
}

Some files were not shown because too many files have changed in this diff Show More