mirror of
https://github.com/rkd77/elinks.git
synced 2025-06-30 22:19:29 -04:00
Merge with http://elinks.cz/elinks.git
This commit is contained in:
commit
93714a3e35
@ -48,6 +48,9 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
|
|||||||
INSTALL_DATA = @INSTALL_DATA@
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||||
|
|
||||||
|
TEST_LIB=$(top_srcdir)/test/libtest.sh
|
||||||
|
export TEST_LIB
|
||||||
|
|
||||||
host = @host@
|
host = @host@
|
||||||
|
|
||||||
ASCIIDOC = @ASCIIDOC@
|
ASCIIDOC = @ASCIIDOC@
|
||||||
|
78
Makefile.lib
78
Makefile.lib
@ -43,7 +43,7 @@ quiet_cmd_ld_objs = " [$(LD_COLOR)LD$(END_COLOR)] $(RELPATH)$@"
|
|||||||
`test -e $(subdir)/lib.o && echo $(subdir)/lib.o`)
|
`test -e $(subdir)/lib.o && echo $(subdir)/lib.o`)
|
||||||
|
|
||||||
quiet_cmd_link = ' [$(LINK_COLOR)LINK$(END_COLOR)] $(RELPATH)$@'
|
quiet_cmd_link = ' [$(LINK_COLOR)LINK$(END_COLOR)] $(RELPATH)$@'
|
||||||
cmd_link = $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
|
cmd_link = $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(2) $(LIBS)
|
||||||
|
|
||||||
quiet_cmd_sparse = ' [SPARSE] $(RELPATH)$(2)'
|
quiet_cmd_sparse = ' [SPARSE] $(RELPATH)$(2)'
|
||||||
cmd_sparse = $(SPARSE) $(DEFS) $(INCLUDES) $(AM_CFLAGS) $(CFLAGS) $(SPARSE_FLAGS) $(2)
|
cmd_sparse = $(SPARSE) $(DEFS) $(INCLUDES) $(AM_CFLAGS) $(CFLAGS) $(SPARSE_FLAGS) $(2)
|
||||||
@ -125,12 +125,15 @@ CLEAN += $(PROG)
|
|||||||
|
|
||||||
all-default: $(LIB_O) $(PROGS) $(MAN1) $(MAN5)
|
all-default: $(LIB_O) $(PROGS) $(MAN1) $(MAN5)
|
||||||
|
|
||||||
|
# Ensure that Makefiles in subdirs are created before we recursive into them
|
||||||
|
init-recursive: init-default
|
||||||
|
|
||||||
init-default:
|
init-default:
|
||||||
@$(foreach subdir,$(sort $(SUBDIRS)), \
|
@$(foreach subdir,$(sort $(SUBDIRS)), \
|
||||||
$(MKINSTALLDIRS) $(subdir) >/dev/null; \
|
$(MKINSTALLDIRS) $(subdir) >/dev/null; \
|
||||||
echo 'include $(SRC)/$(RELPATH)/$(subdir)/Makefile' > $(subdir)/Makefile;)
|
echo 'include $(SRC)/$(RELPATH)/$(subdir)/Makefile' > $(subdir)/Makefile;)
|
||||||
|
|
||||||
clean-default:
|
clean-default: clean-test
|
||||||
@-test -z "$(CLEAN)" || $(RM) $(CLEAN)
|
@-test -z "$(CLEAN)" || $(RM) $(CLEAN)
|
||||||
|
|
||||||
cleanall-default: clean-default
|
cleanall-default: clean-default
|
||||||
@ -141,6 +144,39 @@ ifneq ($(SPARSE),)
|
|||||||
$(call ncmd,sparse,$(file));)
|
$(call ncmd,sparse,$(file));)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
#
|
||||||
|
# Auto-testing infrastructure
|
||||||
|
#
|
||||||
|
|
||||||
|
clean-test:
|
||||||
|
test-default:
|
||||||
|
|
||||||
|
ifdef TEST_PROGS
|
||||||
|
TESTDEPS += $(TESTDEPS-yes)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
test-default: $(TESTS)
|
||||||
|
|
||||||
|
clean-test:
|
||||||
|
@rm -fr trash
|
||||||
|
|
||||||
|
CLEAN += $(TEST_PROGS) $(addsuffix .o,$(TEST_PROGS))
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: $(TESTS)
|
||||||
|
.NOPARALLEL:
|
||||||
|
|
||||||
# sparse is architecture-neutral, which means that we need to tell it
|
# sparse is architecture-neutral, which means that we need to tell it
|
||||||
# explicitly what architecture to check for. Fix this up for yours..
|
# explicitly what architecture to check for. Fix this up for yours..
|
||||||
SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
|
SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
|
||||||
@ -163,29 +199,41 @@ endif
|
|||||||
|
|
||||||
# Recursion:
|
# Recursion:
|
||||||
|
|
||||||
.PHONY: all-recursive install-recursive clean-recursive cleanall-recursive init-recursive check-recursive
|
RULES = all install clean cleanall init check test
|
||||||
|
RECRULES = $(addsuffix -recursive,$(RULES))
|
||||||
|
|
||||||
all-recursive install-recursive clean-recursive cleanall-recursive init-recursive check-recursive:
|
.PHONY: $(RECRULES)
|
||||||
|
|
||||||
|
# The -recursive rules decend all subdirs.
|
||||||
|
$(RECRULES):
|
||||||
ifdef SUBDIRS
|
ifdef SUBDIRS
|
||||||
@$(foreach subdir,$(sort $(SUBDIRS)), \
|
@$(foreach subdir,$(sort $(SUBDIRS)), \
|
||||||
$(call ncmd,recmake,$(subdir),$(subst -recursive,,$@)) || exit 1;)
|
$(call ncmd,recmake,$(subdir),$(subst -recursive,,$@)) || exit 1;)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all: all-recursive all-default all-local
|
# Setup the default sub commands dependency. First decend subdirs then do all
|
||||||
install: install-recursive install-default install-local
|
# the default stuff and finally do any local hooks.
|
||||||
check: check-recursive check-default check-local
|
recdeps = $1-recursive $1-default $1-local
|
||||||
clean: clean-recursive clean-default clean-local
|
all: $(call recdeps,all)
|
||||||
|
check: $(call recdeps,check)
|
||||||
|
cleanall: $(call recdeps,cleanall)
|
||||||
|
clean: $(call recdeps,clean)
|
||||||
|
init: $(call recdeps,init)
|
||||||
|
install: $(call recdeps,install)
|
||||||
|
test: $(call recdeps,test)
|
||||||
|
|
||||||
cleanall: cleanall-recursive cleanall-default
|
# Dummy rules for local hooks
|
||||||
init: init-default init-recursive
|
$(addsuffix -local,$(RULES)):
|
||||||
|
|
||||||
all-local:
|
|
||||||
install-local:
|
|
||||||
clean-local:
|
|
||||||
check-local:
|
|
||||||
|
|
||||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||||
.NOEXPORT:
|
.NOEXPORT:
|
||||||
|
|
||||||
|
# Shell quote;
|
||||||
|
# Result of this needs to be placed inside ''
|
||||||
|
# XXX: Placed here because Vim cannot highlight things right afterwards
|
||||||
|
shq = $(subst ','\'',$(1))
|
||||||
|
# This has surrounding ''
|
||||||
|
shellquote = '$(call shq,$(1))'
|
||||||
|
|
||||||
# vim:syntax=make
|
# vim:syntax=make
|
||||||
|
1102
Unicode/entities.lnx
1102
Unicode/entities.lnx
File diff suppressed because it is too large
Load Diff
1060
Unicode/entities.txt
Normal file
1060
Unicode/entities.txt
Normal file
File diff suppressed because it is too large
Load Diff
@ -2,18 +2,27 @@
|
|||||||
|
|
||||||
echo
|
echo
|
||||||
echo Generating entity table.
|
echo Generating entity table.
|
||||||
(
|
|
||||||
cat entities.lnx | grep '^[ ]*{"' | sort >tmp
|
sed -n '/^[^#]/,$p' < entities.txt | while read line; do \
|
||||||
|
name=$(echo "$line" | cut -f 1); \
|
||||||
|
code=$(echo "$line" | cut -f 3); \
|
||||||
|
desc=$(echo "$line" | cut -f 4 | sed 's/# //'); \
|
||||||
|
test "$code" = "0x????" && continue
|
||||||
|
printf "\t{ %-12s %s }, /* %-46s */\n" \
|
||||||
|
"\"$name\"," "$code" "$desc"; \
|
||||||
|
done | LC_ALL=C sort > tmp
|
||||||
N=`cat tmp | wc -l`
|
N=`cat tmp | wc -l`
|
||||||
echo '/* Automatically generated by gen-ent */'
|
|
||||||
echo
|
cat > ../src/intl/entity.inc <<EOF
|
||||||
echo 'struct entity { char *s; unicode_val_T c; } entities ['`expr $N + 1`'] = {'
|
/* Automatically generated by gen-ent */
|
||||||
cat tmp
|
|
||||||
echo ' {NULL, 0}'
|
struct entity { char *s; unicode_val_T c; } entities [$(expr $N + 1)] = {
|
||||||
echo '};'
|
$(cat tmp)
|
||||||
echo
|
{ NULL, 0 }
|
||||||
echo '#define N_ENTITIES' $N
|
};
|
||||||
) > ../src/intl/entity.inc
|
|
||||||
|
#define N_ENTITIES $N
|
||||||
|
EOF
|
||||||
rm -f tmp
|
rm -f tmp
|
||||||
echo Done.
|
echo Done.
|
||||||
echo
|
echo
|
||||||
|
@ -220,6 +220,3 @@ in the future. So far, we have had no reports from our users that anyone wants
|
|||||||
to switch their bookmarks format frequently, so this is not too high on our
|
to switch their bookmarks format frequently, so this is not too high on our
|
||||||
TODO list. So be sure to tell us if you would like this process to be
|
TODO list. So be sure to tell us if you would like this process to be
|
||||||
simplified rather sooner than later.
|
simplified rather sooner than later.
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
@ -120,6 +120,3 @@ that there are no SpiderMonkey references outside of
|
|||||||
ECMAScript backend, go ahead - you will just need to write an autoconf
|
ECMAScript backend, go ahead - you will just need to write an autoconf
|
||||||
detection for it and tie it to `src/ecmascript/ecmascript.c`, which should be
|
detection for it and tie it to `src/ecmascript/ecmascript.c`, which should be
|
||||||
easy. We await your patches eagerly.
|
easy. We await your patches eagerly.
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
@ -99,6 +99,3 @@ Also, perhaps wider scale of commands should be implemented in ex-mode. The
|
|||||||
code is extremely flexible and it is very trivial to make another ex-mode
|
code is extremely flexible and it is very trivial to make another ex-mode
|
||||||
command handler, it's just that no one has done it yet ;-). Also, more actions
|
command handler, it's just that no one has done it yet ;-). Also, more actions
|
||||||
should be able to take arguments.
|
should be able to take arguments.
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
@ -150,7 +150,3 @@ The new ELinks versions (from 0.9.0 on) send:
|
|||||||
You should therefore check against something like /^ELinks[\/ ]/, since more
|
You should therefore check against something like /^ELinks[\/ ]/, since more
|
||||||
fields can be added inside the parenthesis in subsequent versions. Note that
|
fields can be added inside the parenthesis in subsequent versions. Note that
|
||||||
users can change their User-Agent through the options system.
|
users can change their User-Agent through the options system.
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
@ -31,8 +31,3 @@ pizza, some close location of yourself recommended), we accept drinks, nice
|
|||||||
books, CDs with interesting things, computer equipment and accessories, PDAs,
|
books, CDs with interesting things, computer equipment and accessories, PDAs,
|
||||||
pens + pencils + erasers, and last but not least money. Contact the maintainer,
|
pens + pencils + erasers, and last but not least money. Contact the maintainer,
|
||||||
he'll split the stuff properly amongst himself and other developers >:).
|
he'll split the stuff properly amongst himself and other developers >:).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
@ -5,8 +5,6 @@ Welcome, mere mortal, to the realm of evil unindented code, heaps of one or
|
|||||||
two-letter variables, seas of gotos accompanied with 30-letters labels in Czech
|
two-letter variables, seas of gotos accompanied with 30-letters labels in Czech
|
||||||
language with absolutely no meaning, welcome to the realm of ELinks code!
|
language with absolutely no meaning, welcome to the realm of ELinks code!
|
||||||
|
|
||||||
[We're going to extend this file slowly, basing on daily practice ;]
|
|
||||||
|
|
||||||
Don't take this file as a law. We may or may not be right in these issues.
|
Don't take this file as a law. We may or may not be right in these issues.
|
||||||
|
|
||||||
Motto: I didn't expect someone to look at the source, so it's unreadable.
|
Motto: I didn't expect someone to look at the source, so it's unreadable.
|
||||||
@ -681,6 +679,3 @@ to compile or execute in one of these modes, then rework it.
|
|||||||
|
|
||||||
|
|
||||||
Happy hacking!
|
Happy hacking!
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
@ -74,6 +74,3 @@ include::ecmascript.txt[]
|
|||||||
include::txt/import-features.conf.txt[]
|
include::txt/import-features.conf.txt[]
|
||||||
|
|
||||||
endif::installation-webpage[]
|
endif::installation-webpage[]
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
@ -359,7 +359,3 @@ everything is marked TODO!
|
|||||||
- Insert mode in text-input form-fields.
|
- Insert mode in text-input form-fields.
|
||||||
|
|
||||||
- Menu searching.
|
- Menu searching.
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
@ -559,6 +559,3 @@ More ideas
|
|||||||
- More things are possible, I'm sure. If you have an idea that requires
|
- More things are possible, I'm sure. If you have an idea that requires
|
||||||
another hook or function, contact me (Peter Wang) and I'll see what I can
|
another hook or function, contact me (Peter Wang) and I'll see what I can
|
||||||
do.
|
do.
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
@ -124,6 +124,3 @@ audio/mpeg; xmms '%s'; test=test -n "$DISPLAY";
|
|||||||
application/pdf; xpdf '%s'; test=test -n "$DISPLAY";
|
application/pdf; xpdf '%s'; test=test -n "$DISPLAY";
|
||||||
application/postscript; ps2ascii %s ; copiousoutput
|
application/postscript; ps2ascii %s ; copiousoutput
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
.\" elinks.conf.5
|
.\" elinks.conf.5
|
||||||
.\"
|
.\"
|
||||||
.\" Generated by help2doc (Revision: 1.19) on 09 August 05 using output from ELinks version 0.11.CVS.
|
.\" Generated by help2doc (Revision: 1.19) on 03 January 06 using output from ELinks version 0.12.GIT.
|
||||||
.\"
|
.\"
|
||||||
.\" Copyleft (c) 2002-2004 The ELinks project
|
.\" Copyleft (c) 2002-2004 The ELinks project
|
||||||
.\"
|
.\"
|
||||||
@ -8,7 +8,7 @@
|
|||||||
.\" General Public License. <www.gnu.org/licenses/gpl.html>
|
.\" General Public License. <www.gnu.org/licenses/gpl.html>
|
||||||
.\"
|
.\"
|
||||||
.\" Process this file with groff -man -Tascii elinks.conf.5
|
.\" Process this file with groff -man -Tascii elinks.conf.5
|
||||||
.TH ELINKS.CONF 5 \"09 August 05\"
|
.TH ELINKS.CONF 5 \"03 January 06\"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
elinks.conf \- ELinks configuration file
|
elinks.conf \- ELinks configuration file
|
||||||
@ -313,8 +313,8 @@ are always inserted into a selected text field.
|
|||||||
\f3document.browse.forms.editor\f2 <str>\f1 (default: "")
|
\f3document.browse.forms.editor\f2 <str>\f1 (default: "")
|
||||||
Path to the executable that ELinks should launch when the user
|
Path to the executable that ELinks should launch when the user
|
||||||
requests to edit a textarea with an external editor.
|
requests to edit a textarea with an external editor.
|
||||||
.TP
|
If this is blank, ELinks will use the value of the environmental
|
||||||
\f3variable\f2 $EDITOR.\f1 (variable $EDITOR. If $EDITOR is empty or not set, ELinks will then)
|
variable $EDITOR. If $EDITOR is empty or not set, ELinks will then
|
||||||
default to "vi".
|
default to "vi".
|
||||||
.TP
|
.TP
|
||||||
\f3document.browse.forms.show_formhist\f2 [0|1]\f1 (default: 0)
|
\f3document.browse.forms.show_formhist\f2 [0|1]\f1 (default: 0)
|
||||||
@ -459,6 +459,9 @@ The TABINDEX attribute in HTML elements specifies the order
|
|||||||
in which links should receive focus when using the keyboard
|
in which links should receive focus when using the keyboard
|
||||||
to navigating the document.
|
to navigating the document.
|
||||||
.TP
|
.TP
|
||||||
|
\f3document.browse.links.missing_fragment\f2 [0|1]\f1 (default: 1)
|
||||||
|
Open a message box when document has no tag with given id.
|
||||||
|
.TP
|
||||||
\f3document.browse.links.number_keys_select_link\f2 <num>\f1 (default: 1)
|
\f3document.browse.links.number_keys_select_link\f2 <num>\f1 (default: 1)
|
||||||
Number keys select links rather than specify command prefixes. This
|
Number keys select links rather than specify command prefixes. This
|
||||||
is a tristate:
|
is a tristate:
|
||||||
@ -675,11 +678,10 @@ Default directory color.
|
|||||||
See document.browse.links.color_dirs option.
|
See document.browse.links.color_dirs option.
|
||||||
.TP
|
.TP
|
||||||
\f3document.colors.increase_contrast\f2 [0|1]\f1 (default: 1)
|
\f3document.colors.increase_contrast\f2 [0|1]\f1 (default: 1)
|
||||||
Setting this option to 0 will increase the contrast
|
Increase the contrast between the foreground and background colors
|
||||||
between the foreground and background colors to ensure
|
to ensure readability. For example it disallows dark colors on a
|
||||||
readability. For example it disallows dark colors on a
|
black background. Note, this is different from ensuring the contrast
|
||||||
black background. Note, this is different from ensuring
|
with the ensure_contrast option.
|
||||||
the contrast with the ensure_contrast option.
|
|
||||||
.TP
|
.TP
|
||||||
\f3document.colors.ensure_contrast\f2 [0|1]\f1 (default: 1)
|
\f3document.colors.ensure_contrast\f2 [0|1]\f1 (default: 1)
|
||||||
Makes sure that the back- and foreground color are never equal.
|
Makes sure that the back- and foreground color are never equal.
|
||||||
@ -782,6 +784,8 @@ in dump output.
|
|||||||
.TP
|
.TP
|
||||||
\f3document.dump.separator\f2 <str>\f1 (document.dump.separator <str> (default: ")
|
\f3document.dump.separator\f2 <str>\f1 (document.dump.separator <str> (default: ")
|
||||||
.TP
|
.TP
|
||||||
|
\f3String\f2 Swhich\f1 (String which separates two dumps.)
|
||||||
|
.TP
|
||||||
\f3document.dump.width\f2 <num>\f1 (default: 80)
|
\f3document.dump.width\f2 <num>\f1 (default: 80)
|
||||||
Width of screen in characters when dumping documents.
|
Width of screen in characters when dumping documents.
|
||||||
.PD
|
.PD
|
||||||
@ -877,6 +881,7 @@ A rule for passing URI to an external command.
|
|||||||
The format is:
|
The format is:
|
||||||
%c in the string means the current URL
|
%c in the string means the current URL
|
||||||
%% in the string means '%'
|
%% in the string means '%'
|
||||||
|
Do _not_ put single- or double-quotes around %c.
|
||||||
.SS ECMAScript (ecmascript)
|
.SS ECMAScript (ecmascript)
|
||||||
ECMAScript options.
|
ECMAScript options.
|
||||||
.TP
|
.TP
|
||||||
@ -886,6 +891,10 @@ Whether to run those scripts inside of documents.
|
|||||||
\f3ecmascript.error_reporting\f2 [0|1]\f1 (default: 0)
|
\f3ecmascript.error_reporting\f2 [0|1]\f1 (default: 0)
|
||||||
Open a message box when a script reports an error.
|
Open a message box when a script reports an error.
|
||||||
.TP
|
.TP
|
||||||
|
\f3ecmascript.ignore_noscript\f2 [0|1]\f1 (default: 0)
|
||||||
|
Whether to ignore content enclosed by the <noscript> tag
|
||||||
|
when ECMAScript is enabled.
|
||||||
|
.TP
|
||||||
\f3ecmascript.max_exec_time\f2 <num>\f1 (default: 5)
|
\f3ecmascript.max_exec_time\f2 <num>\f1 (default: 5)
|
||||||
Maximum execution time in seconds for a script.
|
Maximum execution time in seconds for a script.
|
||||||
.PD
|
.PD
|
||||||
@ -1045,6 +1054,13 @@ What IP address to report to the tracker. If set to ""
|
|||||||
no IP address will be sent and the tracker will automatically
|
no IP address will be sent and the tracker will automatically
|
||||||
determine an appropriate IP address.
|
determine an appropriate IP address.
|
||||||
.TP
|
.TP
|
||||||
|
\f3protocol.bittorrent.tracker.key\f2 <str>\f1 (default: "")
|
||||||
|
An additional identification that is not shared with any users.
|
||||||
|
It is intended to allow a client to prove their identity should
|
||||||
|
their IP address change. It is an optional parameter, but some
|
||||||
|
trackers require this parameter. If set to "" no user key will
|
||||||
|
be sent to the tracker.
|
||||||
|
.TP
|
||||||
\f3protocol.bittorrent.tracker.numwant\f2 <num>\f1 (default: 50)
|
\f3protocol.bittorrent.tracker.numwant\f2 <num>\f1 (default: 50)
|
||||||
The maximum number of peers to request from the tracker.
|
The maximum number of peers to request from the tracker.
|
||||||
Set to 0 to use the server default.
|
Set to 0 to use the server default.
|
||||||
@ -1337,7 +1353,7 @@ disable use of the default template rewrite rule.
|
|||||||
Enable dumb prefixes - simple URI abbreviations which can
|
Enable dumb prefixes - simple URI abbreviations which can
|
||||||
be written to the Goto URL dialog instead of actual URIs - i.e.
|
be written to the Goto URL dialog instead of actual URIs - i.e.
|
||||||
if you write 'elinks' there, you are directed to
|
if you write 'elinks' there, you are directed to
|
||||||
http://elinks.or.cz/.
|
http://elinks.cz/.
|
||||||
.TP
|
.TP
|
||||||
\f3protocol.rewrite.enable-smart\f2 [0|1]\f1 (default: 1)
|
\f3protocol.rewrite.enable-smart\f2 [0|1]\f1 (default: 1)
|
||||||
Enable smart prefixes - URI templates triggered by writing
|
Enable smart prefixes - URI templates triggered by writing
|
||||||
@ -2139,10 +2155,15 @@ on the command line or when requested by the goto-url-home action.
|
|||||||
Set to "" if the environment variable WWW_HOME should be used
|
Set to "" if the environment variable WWW_HOME should be used
|
||||||
as homepage URI instead.
|
as homepage URI instead.
|
||||||
.TP
|
.TP
|
||||||
|
\f3ui.sessions.keep_session_active\f2 [0|1]\f1 (default: 0)
|
||||||
|
Keep the session active even if the last terminal exits.
|
||||||
|
.TP
|
||||||
\f3ui.sessions.snapshot\f2 [0|1]\f1 (default: 0)
|
\f3ui.sessions.snapshot\f2 [0|1]\f1 (default: 0)
|
||||||
Automatically save a snapshot of all tabs periodically.
|
Automatically save a snapshot of all tabs periodically.
|
||||||
This will periodically bookmark the tabs of each terminal in a separate folder
|
This will periodically bookmark the tabs of each terminal in a separate folder
|
||||||
for recovery after a crash.
|
for recovery after a crash.
|
||||||
|
.TP
|
||||||
|
\f3This\f2 Tfeature\f1 (This feature requires bookmark support.)
|
||||||
.SS Window tabs (ui.tabs)
|
.SS Window tabs (ui.tabs)
|
||||||
Window tabs settings.
|
Window tabs settings.
|
||||||
.TP
|
.TP
|
||||||
@ -2225,7 +2246,7 @@ in an xterm-like terminal. This way the document's title is
|
|||||||
shown on the window titlebar.
|
shown on the window titlebar.
|
||||||
.SH "DOCUMENT INFO"
|
.SH "DOCUMENT INFO"
|
||||||
.PP
|
.PP
|
||||||
Generated by help2doc (Revision: 1.19) on 09 August 05 using output from ELinks version 0.11.CVS.
|
Generated by help2doc (Revision: 1.19) on 03 January 06 using output from ELinks version 0.12.GIT.
|
||||||
help2doc is distributed with ELinks under the terms of the GPL.
|
help2doc is distributed with ELinks under the terms of the GPL.
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
.BR elinks (1),
|
.BR elinks (1),
|
||||||
|
@ -258,6 +258,10 @@ Follow the current link, forcing reload of the target\&.
|
|||||||
link\-menu
|
link\-menu
|
||||||
Open the link context menu\&.
|
Open the link context menu\&.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
link\-form\-menu
|
||||||
|
Open the form fields menu\&.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
lua\-console
|
lua\-console
|
||||||
Open a Lua console\&.
|
Open a Lua console\&.
|
||||||
|
@ -84,6 +84,3 @@ did not quit your ELinks _completely_ --- if you run multiple ELinks
|
|||||||
instances under a single user on a single system, they "join" together and
|
instances under a single user on a single system, they "join" together and
|
||||||
you must quit (or kill) them all to get rid of the damn thing. But that's a
|
you must quit (or kill) them all to get rid of the damn thing. But that's a
|
||||||
different story.
|
different story.
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
@ -178,6 +178,3 @@ Just enter set mime.type.class.name = "handler", replacing class with the
|
|||||||
class for the mime type, name with the specific name within that class, and
|
class for the mime type, name with the specific name within that class, and
|
||||||
handler with the name for the handler you want to assign to the MIME type.
|
handler with the name for the handler you want to assign to the MIME type.
|
||||||
E.g. you may want to have set mime.type.image.jpeg = "image_viewer".
|
E.g. you may want to have set mime.type.image.jpeg = "image_viewer".
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
@ -83,6 +83,3 @@ example, by running:
|
|||||||
|
|
||||||
new tabs containing `slashdot.org`, `freshmeat.net` and a Google search of elinks
|
new tabs containing `slashdot.org`, `freshmeat.net` and a Google search of elinks
|
||||||
will be opened.
|
will be opened.
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
@ -90,6 +90,3 @@ Whow ! Around 200kb :)
|
|||||||
- it disables fastfind feature, reducing performance, but also reducing a lot
|
- it disables fastfind feature, reducing performance, but also reducing a lot
|
||||||
memory usage, and a bit the executable size.
|
memory usage, and a bit the executable size.
|
||||||
==============================================================================
|
==============================================================================
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
@ -110,6 +110,3 @@ bookmark therein the currently displayed document of each tab:
|
|||||||
- As a mean of crash protection, tabs can periodically be saved so that it is
|
- As a mean of crash protection, tabs can periodically be saved so that it is
|
||||||
later possible to reconstruct opened tabs. In case of a clean shutdown
|
later possible to reconstruct opened tabs. In case of a clean shutdown
|
||||||
periodically saved tabs will be removed.
|
periodically saved tabs will be removed.
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
@ -163,6 +163,3 @@ GNU Screen is VT100-compatible, so select 'VT 100 frames'. GNU Screen also
|
|||||||
supports colors just fine, so select '16 colors', or, if you are running Screen
|
supports colors just fine, so select '16 colors', or, if you are running Screen
|
||||||
within a terminal emulator that supports 256 colors and you have compiled both
|
within a terminal emulator that supports 256 colors and you have compiled both
|
||||||
Screen and ELinks to support it, choose '256 colors'.
|
Screen and ELinks to support it, choose '256 colors'.
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
@ -27,6 +27,7 @@ END_OF_USAGE
|
|||||||
# Option handling {{{1
|
# Option handling {{{1
|
||||||
|
|
||||||
command=
|
command=
|
||||||
|
filter=cat
|
||||||
prev_option=
|
prev_option=
|
||||||
|
|
||||||
for option
|
for option
|
||||||
@ -41,10 +42,12 @@ do
|
|||||||
case "$option" in
|
case "$option" in
|
||||||
--cmdoptions)
|
--cmdoptions)
|
||||||
command="$elinks -long-help"
|
command="$elinks -long-help"
|
||||||
|
filter="sed 0,/^Options:/d"
|
||||||
backend="cmdoptions"
|
backend="cmdoptions"
|
||||||
;;
|
;;
|
||||||
--elinksconf)
|
--elinksconf)
|
||||||
command="$elinks -config-help"
|
command="$elinks -config-help"
|
||||||
|
filter="sed 0,/^Configuration/d"
|
||||||
backend="elinksconf"
|
backend="elinksconf"
|
||||||
;;
|
;;
|
||||||
-)
|
-)
|
||||||
@ -285,7 +288,7 @@ use_log=
|
|||||||
|
|
||||||
$print_header
|
$print_header
|
||||||
|
|
||||||
$command | while read line
|
$command | $filter | while read line
|
||||||
do
|
do
|
||||||
if test -n "$parse_description"
|
if test -n "$parse_description"
|
||||||
then
|
then
|
||||||
@ -323,7 +326,7 @@ do
|
|||||||
case "$line" in
|
case "$line" in
|
||||||
Features:*)
|
Features:*)
|
||||||
;;
|
;;
|
||||||
[A-Z]*:*[a-z]*)
|
[A-Z]*:" ("*[a-z]*)
|
||||||
parse_description=1
|
parse_description=1
|
||||||
title="`echo $line | sed -e 's/\([A-Z]*\):.*/\1/'`"
|
title="`echo $line | sed -e 's/\([A-Z]*\):.*/\1/'`"
|
||||||
path="`echo $line | sed -e 's/.*: (\([a-z_].*\))/\1/'`"
|
path="`echo $line | sed -e 's/.*: (\([a-z_].*\))/\1/'`"
|
||||||
|
@ -87,6 +87,3 @@ advanced CVSweb and Debian package database URI prefixes implemented in the
|
|||||||
sample Lua hooks file. The one disadvantage to this is that you must have Lua
|
sample Lua hooks file. The one disadvantage to this is that you must have Lua
|
||||||
scripting enabled in order to make use of it, and many users don't have Lua
|
scripting enabled in order to make use of it, and many users don't have Lua
|
||||||
installed.
|
installed.
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
@ -12,6 +12,8 @@ PERL = perl
|
|||||||
# xgettext)
|
# xgettext)
|
||||||
POTFILES_ABS_LIST = potfiles.list
|
POTFILES_ABS_LIST = potfiles.list
|
||||||
|
|
||||||
|
POTFILES_REL = $(shell find $(top_srcdir)/src/ -name '*.[ch]' -o -name options.inc -o -name 'actions-*.inc' | sort)
|
||||||
|
|
||||||
quiet_cmd_gmsgfmt = ' [$(PO_COLOR)GMSGFMT$(END_COLOR)] $(RELPATH)$(@)'
|
quiet_cmd_gmsgfmt = ' [$(PO_COLOR)GMSGFMT$(END_COLOR)] $(RELPATH)$(@)'
|
||||||
cmd_gmsgfmt = rm -f -- "$@" && $(GMSGFMT) --statistics -o "$@" -- "$<"
|
cmd_gmsgfmt = rm -f -- "$@" && $(GMSGFMT) --statistics -o "$@" -- "$<"
|
||||||
|
|
||||||
@ -46,7 +48,7 @@ all-local: $(CATALOGS)
|
|||||||
# This pulls in _all_ .c and .h files in the src directory. Even files that has
|
# This pulls in _all_ .c and .h files in the src directory. Even files that has
|
||||||
# not been added to the git repo. Beware of junk entries!
|
# not been added to the git repo. Beware of junk entries!
|
||||||
|
|
||||||
$(srcdir)$(POTFILES_ABS_LIST):
|
$(srcdir)$(POTFILES_ABS_LIST): $(POTFILES_REL)
|
||||||
@( cd $(top_srcdir); \
|
@( cd $(top_srcdir); \
|
||||||
find src/ -type f -name '*.[ch]' -o -name options.inc -o -name 'actions-*.inc' | sort ) \
|
find src/ -type f -name '*.[ch]' -o -name options.inc -o -name 'actions-*.inc' | sort ) \
|
||||||
> $(srcdir)$(POTFILES_ABS_LIST)
|
> $(srcdir)$(POTFILES_ABS_LIST)
|
||||||
@ -69,7 +71,7 @@ $(srcdir)$(PACKAGE).pot: $(srcdir)$(POTFILES_ABS_LIST) $(srcdir)perl/gather-acce
|
|||||||
# either <lang> or <lang>.po when calling make. Example: make update-po PO=is
|
# either <lang> or <lang>.po when calling make. Example: make update-po PO=is
|
||||||
|
|
||||||
update-po: Makefile $(srcdir)$(PACKAGE).pot
|
update-po: Makefile $(srcdir)$(PACKAGE).pot
|
||||||
@test -n "$(srcdir)" && cd $(srcdir)
|
@test -z "$(srcdir)" || cd $(srcdir)
|
||||||
@$(foreach lang,$(basename $(if $(strip $(PO)),$(PO),$(GMOFILES))), \
|
@$(foreach lang,$(basename $(if $(strip $(PO)),$(PO),$(GMOFILES))), \
|
||||||
echo -n "$(lang): "; \
|
echo -n "$(lang): "; \
|
||||||
if $(MSGMERGE) $(srcdir)$(lang).po $(srcdir)$(PACKAGE).pot -o $(lang).new.po; then \
|
if $(MSGMERGE) $(srcdir)$(lang).po $(srcdir)$(PACKAGE).pot -o $(lang).new.po; then \
|
||||||
|
14
po/fr.po
14
po/fr.po
@ -1,13 +1,13 @@
|
|||||||
# French ELinks translation.
|
# French ELinks translation.
|
||||||
# Fabrice Haberer-Proust <fric@gmx.li>
|
# Fabrice Haberer-Proust <fric@gmx.li>
|
||||||
# Laurent Monin <zas@norz.org>, 2001 - 2005
|
# Laurent Monin <zas@norz.org>, 2001 - 2006
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: ELinks 0.11.GIT\n"
|
"Project-Id-Version: ELinks 0.12.GIT\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2006-01-01 17:49+0100\n"
|
"POT-Creation-Date: 2006-01-03 13:41+0100\n"
|
||||||
"PO-Revision-Date: 2006-01-01 17:50+0100\n"
|
"PO-Revision-Date: 2006-01-01 13:42+0100\n"
|
||||||
"Last-Translator: Laurent Monin <zas@norz.org>\n"
|
"Last-Translator: Laurent Monin <zas@norz.org>\n"
|
||||||
"Language-Team: French <zas@norz.org>\n"
|
"Language-Team: French <zas@norz.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@ -4674,7 +4674,7 @@ msgid ""
|
|||||||
"\n"
|
"\n"
|
||||||
"(C) 1999 - 2002 Mikulas Patocka\n"
|
"(C) 1999 - 2002 Mikulas Patocka\n"
|
||||||
"(C) 2001 - 2004 Petr Baudis\n"
|
"(C) 2001 - 2004 Petr Baudis\n"
|
||||||
"(C) 2002 - 2005 Jonas Fonseca\n"
|
"(C) 2002 - 2006 Jonas Fonseca\n"
|
||||||
"and others\n"
|
"and others\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This program is free software; you can redistribute it and/or modify it "
|
"This program is free software; you can redistribute it and/or modify it "
|
||||||
@ -4685,7 +4685,7 @@ msgstr ""
|
|||||||
"\n"
|
"\n"
|
||||||
"(C) 1999 - 2002 Mikulas Patocka\n"
|
"(C) 1999 - 2002 Mikulas Patocka\n"
|
||||||
"(C) 2001 - 2004 Petr Baudis\n"
|
"(C) 2001 - 2004 Petr Baudis\n"
|
||||||
"(C) 2002 - 2005 Jonas Fonseca\n"
|
"(C) 2002 - 2006 Jonas Fonseca\n"
|
||||||
"et d'autres\n"
|
"et d'autres\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Ce programme est un logiciel libre; vous pouvez le redistribuer et/ou le "
|
"Ce programme est un logiciel libre; vous pouvez le redistribuer et/ou le "
|
||||||
@ -5983,7 +5983,7 @@ msgstr ""
|
|||||||
"ici à la place de '.')."
|
"ici à la place de '.')."
|
||||||
|
|
||||||
#. name:
|
#. name:
|
||||||
#: src/mime/backend/default.c:227
|
#: src/mime/backend/default.c:228
|
||||||
msgid "Option system"
|
msgid "Option system"
|
||||||
msgstr "Système de configuration"
|
msgstr "Système de configuration"
|
||||||
|
|
||||||
|
@ -157,13 +157,15 @@ hierbox_ev_kbd(struct dialog_data *dlg_data)
|
|||||||
selected = box->sel;
|
selected = box->sel;
|
||||||
action_id = kbd_action(KEYMAP_MENU, ev, NULL);
|
action_id = kbd_action(KEYMAP_MENU, ev, NULL);
|
||||||
|
|
||||||
if (action_id == ACT_MENU_SELECT) {
|
switch (action_id) {
|
||||||
|
case ACT_MENU_SELECT:
|
||||||
if (!selected) return EVENT_PROCESSED;
|
if (!selected) return EVENT_PROCESSED;
|
||||||
if (selected->type != BI_FOLDER)
|
if (selected->type != BI_FOLDER)
|
||||||
return EVENT_NOT_PROCESSED;
|
return EVENT_NOT_PROCESSED;
|
||||||
selected->expanded = !selected->expanded;
|
selected->expanded = !selected->expanded;
|
||||||
|
break;
|
||||||
|
|
||||||
} else if (action_id == ACT_MENU_UNEXPAND) {
|
case ACT_MENU_UNEXPAND:
|
||||||
/* Recursively unexpand all folders */
|
/* Recursively unexpand all folders */
|
||||||
if (!selected) return EVENT_PROCESSED;
|
if (!selected) return EVENT_PROCESSED;
|
||||||
|
|
||||||
@ -173,8 +175,9 @@ hierbox_ev_kbd(struct dialog_data *dlg_data)
|
|||||||
* whole parent folder will be closed. */
|
* whole parent folder will be closed. */
|
||||||
if (list_empty(selected->child)
|
if (list_empty(selected->child)
|
||||||
|| !selected->expanded) {
|
|| !selected->expanded) {
|
||||||
struct listbox_item *root = box->ops->get_root(selected);
|
struct listbox_item *root;
|
||||||
|
|
||||||
|
root = box->ops->get_root(selected);
|
||||||
if (root) {
|
if (root) {
|
||||||
listbox_sel(widget_data, root);
|
listbox_sel(widget_data, root);
|
||||||
}
|
}
|
||||||
@ -182,23 +185,25 @@ hierbox_ev_kbd(struct dialog_data *dlg_data)
|
|||||||
} else if (selected->type == BI_FOLDER) {
|
} else if (selected->type == BI_FOLDER) {
|
||||||
recursively_set_expanded(selected, 0);
|
recursively_set_expanded(selected, 0);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
} else if (action_id == ACT_MENU_EXPAND) {
|
case ACT_MENU_EXPAND:
|
||||||
/* Recursively expand all folders */
|
/* Recursively expand all folders */
|
||||||
|
|
||||||
if (!selected || selected->type != BI_FOLDER)
|
if (!selected || selected->type != BI_FOLDER)
|
||||||
return EVENT_PROCESSED;
|
return EVENT_PROCESSED;
|
||||||
|
|
||||||
recursively_set_expanded(selected, 1);
|
recursively_set_expanded(selected, 1);
|
||||||
|
break;
|
||||||
|
|
||||||
} else if (action_id == ACT_MENU_SEARCH) {
|
case ACT_MENU_SEARCH:
|
||||||
if (!box->ops->match)
|
if (!box->ops->match)
|
||||||
return EVENT_NOT_PROCESSED;
|
return EVENT_NOT_PROCESSED;
|
||||||
|
|
||||||
push_hierbox_search_button(dlg_data, NULL);
|
push_hierbox_search_button(dlg_data, NULL);
|
||||||
return EVENT_PROCESSED;
|
return EVENT_PROCESSED;
|
||||||
|
|
||||||
} else {
|
default:
|
||||||
return EVENT_NOT_PROCESSED;
|
return EVENT_NOT_PROCESSED;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -230,7 +235,9 @@ hierbox_ev_init(struct dialog_data *dlg_data)
|
|||||||
litem->visible = 1;
|
litem->visible = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EVENT_NOT_PROCESSED; /* FIXME: is this correct ? --Zas */
|
/* Return this so that the generic dialog code will run and initialise
|
||||||
|
* the widgets and stuff. */
|
||||||
|
return EVENT_NOT_PROCESSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static widget_handler_status_T
|
static widget_handler_status_T
|
||||||
@ -254,7 +261,9 @@ hierbox_ev_abort(struct dialog_data *dlg_data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return EVENT_NOT_PROCESSED; /* FIXME: is this correct ? --Zas */
|
/* Return this so that the generic dialog code will run and initialise
|
||||||
|
* the widgets and stuff. */
|
||||||
|
return EVENT_NOT_PROCESSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -312,7 +321,7 @@ hierbox_browser(struct hierbox_browser *browser, struct session *ses)
|
|||||||
dlg->udata = ses;
|
dlg->udata = ses;
|
||||||
dlg->udata2 = browser;
|
dlg->udata2 = browser;
|
||||||
|
|
||||||
add_dlg_listbox(dlg, 12, listbox_data);
|
add_dlg_listbox(dlg, listbox_data);
|
||||||
|
|
||||||
for (button = 0; button < browser->buttons_size; button++) {
|
for (button = 0; button < browser->buttons_size; button++) {
|
||||||
struct hierbox_browser_button *but = &browser->buttons[button];
|
struct hierbox_browser_button *but = &browser->buttons[button];
|
||||||
|
@ -24,14 +24,12 @@
|
|||||||
#define VERTICAL_LISTBOX_MARGIN 3
|
#define VERTICAL_LISTBOX_MARGIN 3
|
||||||
|
|
||||||
void
|
void
|
||||||
add_dlg_listbox(struct dialog *dlg, int height, void *box_data)
|
add_dlg_listbox(struct dialog *dlg, void *box_data)
|
||||||
{
|
{
|
||||||
struct widget *widget = &dlg->widgets[dlg->number_of_widgets++];
|
struct widget *widget = &dlg->widgets[dlg->number_of_widgets++];
|
||||||
|
|
||||||
widget->type = WIDGET_LISTBOX;
|
widget->type = WIDGET_LISTBOX;
|
||||||
widget->data = box_data;
|
widget->data = box_data;
|
||||||
|
|
||||||
widget->info.listbox.height = height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct listbox_data *
|
struct listbox_data *
|
||||||
|
@ -11,12 +11,8 @@ struct terminal;
|
|||||||
struct uri;
|
struct uri;
|
||||||
struct widget_data;
|
struct widget_data;
|
||||||
|
|
||||||
struct widget_info_listbox {
|
|
||||||
int height;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
void add_dlg_listbox(struct dialog *dlg, void *box_data);
|
||||||
void add_dlg_listbox(struct dialog *dlg, int height, void *box_data);
|
|
||||||
|
|
||||||
enum listbox_match {
|
enum listbox_match {
|
||||||
LISTBOX_MATCH_OK,
|
LISTBOX_MATCH_OK,
|
||||||
|
@ -42,7 +42,6 @@ struct widget {
|
|||||||
union {
|
union {
|
||||||
struct widget_info_checkbox checkbox;
|
struct widget_info_checkbox checkbox;
|
||||||
struct widget_info_field field;
|
struct widget_info_field field;
|
||||||
struct widget_info_listbox listbox;
|
|
||||||
struct widget_info_button button;
|
struct widget_info_button button;
|
||||||
struct widget_info_text text;
|
struct widget_info_text text;
|
||||||
} info;
|
} info;
|
||||||
|
@ -194,7 +194,7 @@ static struct option_info config_options_info[] = {
|
|||||||
INIT_OPT_STRING("document.browse.forms", N_("External editor"),
|
INIT_OPT_STRING("document.browse.forms", N_("External editor"),
|
||||||
"editor", 0, "",
|
"editor", 0, "",
|
||||||
N_("Path to the executable that ELinks should launch when the user\n"
|
N_("Path to the executable that ELinks should launch when the user\n"
|
||||||
"requests to edit a textarea with an external editor.\n\n"
|
"requests to edit a textarea with an external editor.\n"
|
||||||
"If this is blank, ELinks will use the value of the environmental\n"
|
"If this is blank, ELinks will use the value of the environmental\n"
|
||||||
"variable $EDITOR. If $EDITOR is empty or not set, ELinks will then\n"
|
"variable $EDITOR. If $EDITOR is empty or not set, ELinks will then\n"
|
||||||
"default to \"vi\".")),
|
"default to \"vi\".")),
|
||||||
@ -731,7 +731,7 @@ static struct option_info config_options_info[] = {
|
|||||||
N_("A rule for passing URI to an external command.\n"
|
N_("A rule for passing URI to an external command.\n"
|
||||||
"The format is:\n"
|
"The format is:\n"
|
||||||
"%c in the string means the current URL\n"
|
"%c in the string means the current URL\n"
|
||||||
"%% in the string means '%'\n\n"
|
"%% in the string means '%'\n"
|
||||||
"Do _not_ put single- or double-quotes around %c.")),
|
"Do _not_ put single- or double-quotes around %c.")),
|
||||||
|
|
||||||
/* Keep options in alphabetical order. */
|
/* Keep options in alphabetical order. */
|
||||||
|
@ -144,7 +144,7 @@ menu_copying(struct terminal *term, void *xxx, void *xxxx)
|
|||||||
"\n"
|
"\n"
|
||||||
"(C) 1999 - 2002 Mikulas Patocka\n"
|
"(C) 1999 - 2002 Mikulas Patocka\n"
|
||||||
"(C) 2001 - 2004 Petr Baudis\n"
|
"(C) 2001 - 2004 Petr Baudis\n"
|
||||||
"(C) 2002 - 2005 Jonas Fonseca\n"
|
"(C) 2002 - 2006 Jonas Fonseca\n"
|
||||||
"and others\n"
|
"and others\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This program is free software; you can redistribute it "
|
"This program is free software; you can redistribute it "
|
||||||
|
@ -61,11 +61,11 @@ struct dom_renderer {
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
init_template(struct screen_char *template, struct document_options *options,
|
init_template(struct screen_char *template, struct document_options *options,
|
||||||
color_T background, color_T foreground)
|
color_T background, color_T foreground, enum screen_char_attr attr)
|
||||||
{
|
{
|
||||||
struct color_pair colors = INIT_COLOR_PAIR(background, foreground);
|
struct color_pair colors = INIT_COLOR_PAIR(background, foreground);
|
||||||
|
|
||||||
template->attr = 0;
|
template->attr = attr;
|
||||||
template->data = ' ';
|
template->data = ' ';
|
||||||
set_term_color(template, &colors,
|
set_term_color(template, &colors,
|
||||||
options->color_flags, options->color_mode);
|
options->color_flags, options->color_mode);
|
||||||
@ -115,6 +115,7 @@ init_dom_renderer(struct dom_renderer *renderer, struct document *document,
|
|||||||
struct screen_char *template = &renderer->styles[type];
|
struct screen_char *template = &renderer->styles[type];
|
||||||
color_T background = document->options.default_bg;
|
color_T background = document->options.default_bg;
|
||||||
color_T foreground = document->options.default_fg;
|
color_T foreground = document->options.default_fg;
|
||||||
|
enum screen_char_attr attr = 0;
|
||||||
static int i_want_struct_module_for_dom;
|
static int i_want_struct_module_for_dom;
|
||||||
|
|
||||||
struct dom_string *name = get_dom_node_type_name(type);
|
struct dom_string *name = get_dom_node_type_name(type);
|
||||||
@ -157,9 +158,31 @@ init_dom_renderer(struct dom_renderer *renderer, struct document *document,
|
|||||||
|
|
||||||
property = get_css_property(properties, CSS_PT_COLOR);
|
property = get_css_property(properties, CSS_PT_COLOR);
|
||||||
if (property) foreground = property->value.color;
|
if (property) foreground = property->value.color;
|
||||||
|
|
||||||
|
property = get_css_property(properties, CSS_PT_FONT_WEIGHT);
|
||||||
|
if (property) {
|
||||||
|
if (property->value.font_attribute.add & AT_BOLD)
|
||||||
|
attr |= SCREEN_ATTR_BOLD;
|
||||||
}
|
}
|
||||||
|
|
||||||
init_template(template, &document->options, background, foreground);
|
property = get_css_property(properties, CSS_PT_FONT_STYLE);
|
||||||
|
if (property) {
|
||||||
|
if (property->value.font_attribute.add & AT_UNDERLINE)
|
||||||
|
attr |= SCREEN_ATTR_UNDERLINE;
|
||||||
|
|
||||||
|
if (property->value.font_attribute.add & AT_ITALIC)
|
||||||
|
attr |= SCREEN_ATTR_ITALIC;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
property = get_css_property(properties, CSS_PT_TEXT_DECORATION);
|
||||||
|
if (property) {
|
||||||
|
if (property->value.font_attribute.add & AT_UNDERLINE)
|
||||||
|
attr |= SCREEN_ATTR_UNDERLINE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init_template(template, &document->options, background, foreground, attr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -361,7 +384,7 @@ add_dom_link(struct dom_renderer *renderer, unsigned char *string, int length)
|
|||||||
link->number = document->nlinks;
|
link->number = document->nlinks;
|
||||||
|
|
||||||
init_template(&template, &document->options,
|
init_template(&template, &document->options,
|
||||||
link->color.background, link->color.foreground);
|
link->color.background, link->color.foreground, 0);
|
||||||
|
|
||||||
render_dom_text(renderer, &template, string, length);
|
render_dom_text(renderer, &template, string, length);
|
||||||
|
|
||||||
@ -665,7 +688,6 @@ render_dom_document(struct cache_entry *cached, struct document *document,
|
|||||||
struct string *buffer)
|
struct string *buffer)
|
||||||
{
|
{
|
||||||
unsigned char *head = empty_string_or_(cached->head);
|
unsigned char *head = empty_string_or_(cached->head);
|
||||||
struct dom_node *root;
|
|
||||||
struct dom_renderer renderer;
|
struct dom_renderer renderer;
|
||||||
struct conv_table *convert_table;
|
struct conv_table *convert_table;
|
||||||
struct sgml_parser *parser;
|
struct sgml_parser *parser;
|
||||||
@ -674,6 +696,7 @@ render_dom_document(struct cache_entry *cached, struct document *document,
|
|||||||
size_t length = strlen(string);
|
size_t length = strlen(string);
|
||||||
struct dom_string uri = INIT_DOM_STRING(string, length);
|
struct dom_string uri = INIT_DOM_STRING(string, length);
|
||||||
struct dom_string source = INIT_DOM_STRING(buffer->source, buffer->length);
|
struct dom_string source = INIT_DOM_STRING(buffer->source, buffer->length);
|
||||||
|
enum sgml_parser_code code;
|
||||||
|
|
||||||
assert(document->options.plain);
|
assert(document->options.plain);
|
||||||
|
|
||||||
@ -707,14 +730,18 @@ render_dom_document(struct cache_entry *cached, struct document *document,
|
|||||||
doctype = SGML_DOCTYPE_HTML;
|
doctype = SGML_DOCTYPE_HTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
parser = init_sgml_parser(SGML_PARSER_STREAM, doctype, &uri);
|
parser = init_sgml_parser(SGML_PARSER_STREAM, doctype, &uri, 0);
|
||||||
if (!parser) return;
|
if (!parser) return;
|
||||||
|
|
||||||
add_dom_stack_context(&parser->stack, &renderer,
|
add_dom_stack_context(&parser->stack, &renderer,
|
||||||
&dom_source_renderer_context_info);
|
&dom_source_renderer_context_info);
|
||||||
|
|
||||||
root = parse_sgml(parser, &source);
|
/* FIXME: When rendering this way we don't really care about the code.
|
||||||
if (root) {
|
* However, it will be useful when we will be able to also
|
||||||
|
* incrementally parse new data. This will require the parser to live
|
||||||
|
* during the fetching of data. */
|
||||||
|
code = parse_sgml(parser, &source, 1);
|
||||||
|
if (parser->root) {
|
||||||
assert(parser->stack.depth == 1);
|
assert(parser->stack.depth == 1);
|
||||||
|
|
||||||
get_dom_stack_top(&parser->stack)->immutable = 0;
|
get_dom_stack_top(&parser->stack)->immutable = 0;
|
||||||
|
@ -6,7 +6,4 @@ OBJS = node.o select.o stack.o scanner.o
|
|||||||
|
|
||||||
SUBDIRS-$(CONFIG_DEBUG) += test
|
SUBDIRS-$(CONFIG_DEBUG) += test
|
||||||
|
|
||||||
test: all
|
|
||||||
make test -C test
|
|
||||||
|
|
||||||
include $(top_srcdir)/Makefile.lib
|
include $(top_srcdir)/Makefile.lib
|
||||||
|
@ -154,7 +154,8 @@ init_dom_scanner_info(struct dom_scanner_info *scanner_info)
|
|||||||
|
|
||||||
void
|
void
|
||||||
init_dom_scanner(struct dom_scanner *scanner, struct dom_scanner_info *scanner_info,
|
init_dom_scanner(struct dom_scanner *scanner, struct dom_scanner_info *scanner_info,
|
||||||
struct dom_string *string, int state, int count_lines)
|
struct dom_string *string, int state, int count_lines, int complete,
|
||||||
|
int check_complete)
|
||||||
{
|
{
|
||||||
if (!scanner_info->initialized) {
|
if (!scanner_info->initialized) {
|
||||||
init_dom_scanner_info(scanner_info);
|
init_dom_scanner_info(scanner_info);
|
||||||
@ -170,6 +171,8 @@ init_dom_scanner(struct dom_scanner *scanner, struct dom_scanner_info *scanner_i
|
|||||||
scanner->info = scanner_info;
|
scanner->info = scanner_info;
|
||||||
scanner->state = state;
|
scanner->state = state;
|
||||||
scanner->count_lines = !!count_lines;
|
scanner->count_lines = !!count_lines;
|
||||||
|
scanner->incomplete = !complete;
|
||||||
|
scanner->check_complete = !!check_complete;
|
||||||
scanner->lineno = scanner->count_lines;
|
scanner->lineno = scanner->count_lines;
|
||||||
scanner->info->scan(scanner);
|
scanner->info->scan(scanner);
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,8 @@ struct dom_scanner_info {
|
|||||||
|
|
||||||
/* Initializes the scanner. */
|
/* Initializes the scanner. */
|
||||||
void init_dom_scanner(struct dom_scanner *scanner, struct dom_scanner_info *scanner_info,
|
void init_dom_scanner(struct dom_scanner *scanner, struct dom_scanner_info *scanner_info,
|
||||||
struct dom_string *string, int state, int count_lines);
|
struct dom_string *string, int state, int count_lines, int complete,
|
||||||
|
int check_complete);
|
||||||
|
|
||||||
/* The number of tokens in the scanners token table:
|
/* The number of tokens in the scanners token table:
|
||||||
* At best it should be big enough to contain properties with space separated
|
* At best it should be big enough to contain properties with space separated
|
||||||
@ -123,8 +124,14 @@ struct dom_scanner {
|
|||||||
int line;
|
int line;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
unsigned int count_lines:1;
|
/* The following two flags are used when parsing is incremental and
|
||||||
unsigned int lineno;
|
* the scanner must ensure that only tokens that are complete are
|
||||||
|
* generated. */
|
||||||
|
unsigned int check_complete:1; /* Only generate complete tokens */
|
||||||
|
unsigned int incomplete:1; /* The scanned string is incomplete */
|
||||||
|
|
||||||
|
unsigned int count_lines:1; /* Is line counting enbaled? */
|
||||||
|
unsigned int lineno; /* Line # of the last scanned token */
|
||||||
|
|
||||||
/* Some state indicator only meaningful to the scanner internals */
|
/* Some state indicator only meaningful to the scanner internals */
|
||||||
int state;
|
int state;
|
||||||
|
@ -391,7 +391,7 @@ parse_dom_select(struct dom_select *select, struct dom_stack *stack,
|
|||||||
struct dom_scanner scanner;
|
struct dom_scanner scanner;
|
||||||
struct dom_select_node sel;
|
struct dom_select_node sel;
|
||||||
|
|
||||||
init_dom_scanner(&scanner, &dom_css_scanner_info, string, 0, 0);
|
init_dom_scanner(&scanner, &dom_css_scanner_info, string, 0, 0, 1, 0);
|
||||||
|
|
||||||
memset(&sel, 0, sizeof(sel));
|
memset(&sel, 0, sizeof(sel));
|
||||||
|
|
||||||
@ -530,7 +530,7 @@ init_dom_select(enum dom_select_syntax syntax, struct dom_string *string)
|
|||||||
struct dom_stack stack;
|
struct dom_stack stack;
|
||||||
enum dom_exception_code code;
|
enum dom_exception_code code;
|
||||||
|
|
||||||
init_dom_stack(&stack, DOM_STACK_KEEP_NODES);
|
init_dom_stack(&stack, DOM_STACK_FLAG_NONE);
|
||||||
add_dom_stack_tracer(&stack, "init-select: ");
|
add_dom_stack_tracer(&stack, "init-select: ");
|
||||||
|
|
||||||
code = parse_dom_select(select, &stack, string);
|
code = parse_dom_select(select, &stack, string);
|
||||||
@ -1060,12 +1060,12 @@ select_dom_nodes(struct dom_select *select, struct dom_node *root)
|
|||||||
|
|
||||||
select_data.select = select;;
|
select_data.select = select;;
|
||||||
|
|
||||||
init_dom_stack(&stack, DOM_STACK_KEEP_NODES);
|
init_dom_stack(&stack, DOM_STACK_FLAG_NONE);
|
||||||
add_dom_stack_context(&stack, &select_data,
|
add_dom_stack_context(&stack, &select_data,
|
||||||
&dom_select_context_info);
|
&dom_select_context_info);
|
||||||
add_dom_stack_tracer(&stack, "select-tree: ");
|
add_dom_stack_tracer(&stack, "select-tree: ");
|
||||||
|
|
||||||
init_dom_stack(&select_data.stack, DOM_STACK_KEEP_NODES);
|
init_dom_stack(&select_data.stack, DOM_STACK_FLAG_NONE);
|
||||||
add_dom_stack_context(&select_data.stack, &select_data,
|
add_dom_stack_context(&select_data.stack, &select_data,
|
||||||
&dom_select_data_context_info);
|
&dom_select_data_context_info);
|
||||||
add_dom_stack_tracer(&select_data.stack, "select-match: ");
|
add_dom_stack_tracer(&select_data.stack, "select-match: ");
|
||||||
|
@ -154,7 +154,7 @@ add_sgml_node(struct dom_stack *stack, enum dom_node_type type, struct dom_scann
|
|||||||
|
|
||||||
/* SGML parser main handling: */
|
/* SGML parser main handling: */
|
||||||
|
|
||||||
static inline void
|
static inline enum sgml_parser_code
|
||||||
parse_sgml_attributes(struct dom_stack *stack, struct dom_scanner *scanner)
|
parse_sgml_attributes(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||||
{
|
{
|
||||||
struct dom_scanner_token name;
|
struct dom_scanner_token name;
|
||||||
@ -179,22 +179,30 @@ parse_sgml_attributes(struct dom_stack *stack, struct dom_scanner *scanner)
|
|||||||
case SGML_TOKEN_ELEMENT_BEGIN:
|
case SGML_TOKEN_ELEMENT_BEGIN:
|
||||||
case SGML_TOKEN_ELEMENT_END:
|
case SGML_TOKEN_ELEMENT_END:
|
||||||
case SGML_TOKEN_ELEMENT_EMPTY_END:
|
case SGML_TOKEN_ELEMENT_EMPTY_END:
|
||||||
return;
|
return SGML_PARSER_CODE_OK;
|
||||||
|
|
||||||
case SGML_TOKEN_IDENT:
|
case SGML_TOKEN_IDENT:
|
||||||
copy_struct(&name, token);
|
copy_struct(&name, token);
|
||||||
|
|
||||||
/* Skip the attribute name token */
|
/* Skip the attribute name token */
|
||||||
token = get_next_dom_scanner_token(scanner);
|
token = get_next_dom_scanner_token(scanner);
|
||||||
|
|
||||||
if (token && token->type == '=') {
|
if (token && token->type == '=') {
|
||||||
/* If the token is not a valid value token
|
/* If the token is not a valid value token
|
||||||
* ignore it. */
|
* ignore it. */
|
||||||
token = get_next_dom_scanner_token(scanner);
|
token = get_next_dom_scanner_token(scanner);
|
||||||
|
if (token && token->type == SGML_TOKEN_INCOMPLETE)
|
||||||
|
return SGML_PARSER_CODE_INCOMPLETE;
|
||||||
|
|
||||||
if (token
|
if (token
|
||||||
&& token->type != SGML_TOKEN_IDENT
|
&& token->type != SGML_TOKEN_IDENT
|
||||||
&& token->type != SGML_TOKEN_ATTRIBUTE
|
&& token->type != SGML_TOKEN_ATTRIBUTE
|
||||||
&& token->type != SGML_TOKEN_STRING)
|
&& token->type != SGML_TOKEN_STRING)
|
||||||
token = NULL;
|
token = NULL;
|
||||||
|
|
||||||
|
} else if (token && token->type == SGML_TOKEN_INCOMPLETE) {
|
||||||
|
return SGML_PARSER_CODE_INCOMPLETE;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
token = NULL;
|
token = NULL;
|
||||||
}
|
}
|
||||||
@ -206,14 +214,18 @@ parse_sgml_attributes(struct dom_stack *stack, struct dom_scanner *scanner)
|
|||||||
skip_dom_scanner_token(scanner);
|
skip_dom_scanner_token(scanner);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SGML_TOKEN_INCOMPLETE:
|
||||||
|
return SGML_PARSER_CODE_INCOMPLETE;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
skip_dom_scanner_token(scanner);
|
skip_dom_scanner_token(scanner);
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
return SGML_PARSER_CODE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum sgml_parser_code
|
||||||
parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
|
parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
|
||||||
{
|
{
|
||||||
struct dom_scanner_token target;
|
struct dom_scanner_token target;
|
||||||
@ -235,7 +247,12 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (token->type == SGML_TOKEN_ELEMENT_BEGIN) {
|
if (token->type == SGML_TOKEN_ELEMENT_BEGIN) {
|
||||||
parse_sgml_attributes(stack, scanner);
|
enum sgml_parser_code code;
|
||||||
|
|
||||||
|
code = parse_sgml_attributes(stack, scanner);
|
||||||
|
if (code != SGML_PARSER_CODE_OK)
|
||||||
|
return code;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
skip_dom_scanner_token(scanner);
|
skip_dom_scanner_token(scanner);
|
||||||
}
|
}
|
||||||
@ -294,7 +311,8 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
|
|||||||
|
|
||||||
/* Skip the target token */
|
/* Skip the target token */
|
||||||
token = get_next_dom_scanner_token(scanner);
|
token = get_next_dom_scanner_token(scanner);
|
||||||
if (!token) break;
|
if (!token || token->type == SGML_TOKEN_INCOMPLETE)
|
||||||
|
return SGML_PARSER_CODE_INCOMPLETE;
|
||||||
|
|
||||||
assert(token->type == SGML_TOKEN_PROCESS_DATA);
|
assert(token->type == SGML_TOKEN_PROCESS_DATA);
|
||||||
|
|
||||||
@ -305,13 +323,20 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
|
|||||||
/* Parse the <?xml data="attributes"?>. */
|
/* Parse the <?xml data="attributes"?>. */
|
||||||
struct dom_scanner attr_scanner;
|
struct dom_scanner attr_scanner;
|
||||||
|
|
||||||
|
/* The attribute souce is complete. */
|
||||||
init_dom_scanner(&attr_scanner, &sgml_scanner_info,
|
init_dom_scanner(&attr_scanner, &sgml_scanner_info,
|
||||||
&token->string, SGML_STATE_ELEMENT,
|
&token->string, SGML_STATE_ELEMENT,
|
||||||
scanner->count_lines);
|
scanner->count_lines, 1, 0);
|
||||||
|
|
||||||
if (dom_scanner_has_tokens(&attr_scanner))
|
if (dom_scanner_has_tokens(&attr_scanner)) {
|
||||||
|
/* Ignore parser codes from this
|
||||||
|
* enhanced parsing of attributes. It
|
||||||
|
* is really just a simple way to try
|
||||||
|
* and support xml and xml-stylesheet
|
||||||
|
* instructions. */
|
||||||
parse_sgml_attributes(stack, &attr_scanner);
|
parse_sgml_attributes(stack, &attr_scanner);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pop_dom_node(stack);
|
pop_dom_node(stack);
|
||||||
skip_dom_scanner_token(scanner);
|
skip_dom_scanner_token(scanner);
|
||||||
@ -322,6 +347,9 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
|
|||||||
skip_dom_scanner_token(scanner);
|
skip_dom_scanner_token(scanner);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SGML_TOKEN_INCOMPLETE:
|
||||||
|
return SGML_PARSER_CODE_INCOMPLETE;
|
||||||
|
|
||||||
case SGML_TOKEN_SPACE:
|
case SGML_TOKEN_SPACE:
|
||||||
case SGML_TOKEN_TEXT:
|
case SGML_TOKEN_TEXT:
|
||||||
default:
|
default:
|
||||||
@ -329,30 +357,34 @@ parse_sgml_plain(struct dom_stack *stack, struct dom_scanner *scanner)
|
|||||||
skip_dom_scanner_token(scanner);
|
skip_dom_scanner_token(scanner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return SGML_PARSER_CODE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dom_node *
|
enum sgml_parser_code
|
||||||
parse_sgml(struct sgml_parser *parser, struct dom_string *buffer)
|
parse_sgml(struct sgml_parser *parser, struct dom_string *buffer, int complete)
|
||||||
{
|
{
|
||||||
struct sgml_parsing_state *parsing;
|
struct sgml_parsing_state *parsing;
|
||||||
|
enum sgml_parser_code code;
|
||||||
|
|
||||||
|
if (complete)
|
||||||
|
parser->flags |= SGML_PARSER_COMPLETE;
|
||||||
|
|
||||||
if (!parser->root) {
|
if (!parser->root) {
|
||||||
parser->root = add_sgml_document(&parser->stack, &parser->uri);
|
parser->root = add_sgml_document(&parser->stack, &parser->uri);
|
||||||
if (!parser->root)
|
if (!parser->root)
|
||||||
return NULL;
|
return SGML_PARSER_CODE_MEM_ALLOC;
|
||||||
get_dom_stack_top(&parser->stack)->immutable = 1;
|
get_dom_stack_top(&parser->stack)->immutable = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
parsing = init_sgml_parsing_state(parser, buffer);
|
parsing = init_sgml_parsing_state(parser, buffer);
|
||||||
if (!parsing) return NULL;
|
if (!parsing) return SGML_PARSER_CODE_MEM_ALLOC;
|
||||||
|
|
||||||
/* FIXME: Make parse_sgml_plain() return something (error code or if
|
code = parse_sgml_plain(&parser->stack, &parsing->scanner);
|
||||||
* can be guarenteed a root node). */
|
|
||||||
parse_sgml_plain(&parser->stack, &parsing->scanner);
|
|
||||||
|
|
||||||
pop_dom_node(&parser->parsing);
|
pop_dom_node(&parser->parsing);
|
||||||
|
|
||||||
return parser->root;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -368,11 +400,14 @@ sgml_parsing_push(struct dom_stack *stack, struct dom_node *node, void *data)
|
|||||||
{
|
{
|
||||||
struct sgml_parser *parser = get_sgml_parser(stack);
|
struct sgml_parser *parser = get_sgml_parser(stack);
|
||||||
struct sgml_parsing_state *parsing = data;
|
struct sgml_parsing_state *parsing = data;
|
||||||
|
int count_lines = !!(parser->flags & SGML_PARSER_COUNT_LINES);
|
||||||
|
int complete = !!(parser->flags & SGML_PARSER_COMPLETE);
|
||||||
|
int incremental = !!(parser->flags & SGML_PARSER_INCREMENTAL);
|
||||||
|
|
||||||
parsing->depth = parser->stack.depth;
|
parsing->depth = parser->stack.depth;
|
||||||
get_dom_stack_top(&parser->stack)->immutable = 1;
|
get_dom_stack_top(&parser->stack)->immutable = 1;
|
||||||
init_dom_scanner(&parsing->scanner, &sgml_scanner_info, &node->string,
|
init_dom_scanner(&parsing->scanner, &sgml_scanner_info, &node->string,
|
||||||
SGML_STATE_TEXT, 0);
|
SGML_STATE_TEXT, count_lines, complete, incremental);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -443,6 +478,25 @@ init_sgml_parsing_state(struct sgml_parser *parser, struct dom_string *buffer)
|
|||||||
return get_dom_stack_state_data(parser->parsing.contexts[0], state);
|
return get_dom_stack_state_data(parser->parsing.contexts[0], state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
get_sgml_parser_line_number(struct sgml_parser *parser)
|
||||||
|
{
|
||||||
|
struct dom_stack_state *state;
|
||||||
|
struct sgml_parsing_state *pstate;
|
||||||
|
|
||||||
|
assert(parser->flags & SGML_PARSER_COUNT_LINES);
|
||||||
|
|
||||||
|
if (dom_stack_is_empty(&parser->parsing))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
state = get_dom_stack_top(&parser->parsing);
|
||||||
|
pstate = get_dom_stack_state_data(parser->parsing.contexts[0], state);
|
||||||
|
|
||||||
|
assert(pstate->scanner.count_lines && pstate->scanner.lineno);
|
||||||
|
|
||||||
|
return pstate->scanner.lineno;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Parser creation and destruction: */
|
/* Parser creation and destruction: */
|
||||||
|
|
||||||
@ -486,10 +540,10 @@ static struct dom_stack_context_info sgml_parser_context_info = {
|
|||||||
|
|
||||||
struct sgml_parser *
|
struct sgml_parser *
|
||||||
init_sgml_parser(enum sgml_parser_type type, enum sgml_document_type doctype,
|
init_sgml_parser(enum sgml_parser_type type, enum sgml_document_type doctype,
|
||||||
struct dom_string *uri)
|
struct dom_string *uri, enum sgml_parser_flag flags)
|
||||||
{
|
{
|
||||||
struct sgml_parser *parser;
|
struct sgml_parser *parser;
|
||||||
enum dom_stack_flag flags = 0;
|
enum dom_stack_flag stack_flags = 0;
|
||||||
|
|
||||||
parser = mem_calloc(1, sizeof(*parser));
|
parser = mem_calloc(1, sizeof(*parser));
|
||||||
if (!parser) return NULL;
|
if (!parser) return NULL;
|
||||||
@ -500,18 +554,19 @@ init_sgml_parser(enum sgml_parser_type type, enum sgml_document_type doctype,
|
|||||||
}
|
}
|
||||||
|
|
||||||
parser->type = type;
|
parser->type = type;
|
||||||
|
parser->flags = flags;
|
||||||
parser->info = get_sgml_info(doctype);
|
parser->info = get_sgml_info(doctype);
|
||||||
|
|
||||||
if (type == SGML_PARSER_TREE)
|
if (type == SGML_PARSER_STREAM)
|
||||||
flags |= DOM_STACK_KEEP_NODES;
|
stack_flags |= DOM_STACK_FLAG_FREE_NODES;
|
||||||
|
|
||||||
init_dom_stack(&parser->stack, flags);
|
init_dom_stack(&parser->stack, stack_flags);
|
||||||
/* FIXME: Some sgml backend specific callbacks? Handle HTML script tags,
|
/* FIXME: Some sgml backend specific callbacks? Handle HTML script tags,
|
||||||
* and feed document.write() data back to the parser. */
|
* and feed document.write() data back to the parser. */
|
||||||
add_dom_stack_context(&parser->stack, parser, &sgml_parser_context_info);
|
add_dom_stack_context(&parser->stack, parser, &sgml_parser_context_info);
|
||||||
|
|
||||||
/* Don't keep the 'fake' text nodes that holds the parsing data. */
|
/* Don't keep the 'fake' text nodes that holds the parsing data. */
|
||||||
init_dom_stack(&parser->parsing, 0);
|
init_dom_stack(&parser->parsing, DOM_STACK_FLAG_FREE_NODES);
|
||||||
add_dom_stack_context(&parser->parsing, parser, &sgml_parsing_context_info);
|
add_dom_stack_context(&parser->parsing, parser, &sgml_parsing_context_info);
|
||||||
|
|
||||||
return parser;
|
return parser;
|
||||||
|
@ -22,6 +22,12 @@ enum sgml_parser_type {
|
|||||||
SGML_PARSER_STREAM,
|
SGML_PARSER_STREAM,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum sgml_parser_flag {
|
||||||
|
SGML_PARSER_COUNT_LINES = 1,
|
||||||
|
SGML_PARSER_COMPLETE = 2,
|
||||||
|
SGML_PARSER_INCREMENTAL = 4,
|
||||||
|
};
|
||||||
|
|
||||||
struct sgml_parser_state {
|
struct sgml_parser_state {
|
||||||
/* Info about the properties of the node contained by state.
|
/* Info about the properties of the node contained by state.
|
||||||
* This is only meaningful to element and attribute nodes. For
|
* This is only meaningful to element and attribute nodes. For
|
||||||
@ -34,6 +40,7 @@ struct sgml_parser_state {
|
|||||||
|
|
||||||
struct sgml_parser {
|
struct sgml_parser {
|
||||||
enum sgml_parser_type type; /* Stream or tree */
|
enum sgml_parser_type type; /* Stream or tree */
|
||||||
|
enum sgml_parser_flag flags; /* Flags that control the behaviour */
|
||||||
|
|
||||||
struct sgml_info *info; /* Backend dependent info */
|
struct sgml_info *info; /* Backend dependent info */
|
||||||
|
|
||||||
@ -46,10 +53,23 @@ struct sgml_parser {
|
|||||||
|
|
||||||
struct sgml_parser *
|
struct sgml_parser *
|
||||||
init_sgml_parser(enum sgml_parser_type type, enum sgml_document_type doctype,
|
init_sgml_parser(enum sgml_parser_type type, enum sgml_document_type doctype,
|
||||||
struct dom_string *uri);
|
struct dom_string *uri, enum sgml_parser_flag flags);
|
||||||
|
|
||||||
void done_sgml_parser(struct sgml_parser *parser);
|
void done_sgml_parser(struct sgml_parser *parser);
|
||||||
|
|
||||||
struct dom_node *parse_sgml(struct sgml_parser *parser, struct dom_string *buffer);
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum sgml_parser_code
|
||||||
|
parse_sgml(struct sgml_parser *parser, struct dom_string *buffer, int complete);
|
||||||
|
|
||||||
|
unsigned int get_sgml_parser_line_number(struct sgml_parser *parser);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -98,6 +98,24 @@ skip_sgml_space(struct dom_scanner *scanner, unsigned char **string)
|
|||||||
*string = pos;
|
*string = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define check_sgml_incomplete(scanner, string) \
|
||||||
|
((scanner)->check_complete \
|
||||||
|
&& (scanner)->incomplete \
|
||||||
|
&& (string) == (scanner)->end)
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_sgml_incomplete(struct dom_scanner *scanner, struct dom_scanner_token *token)
|
||||||
|
{
|
||||||
|
size_t left = scanner->end - scanner->position;
|
||||||
|
|
||||||
|
assert(left > 0);
|
||||||
|
|
||||||
|
token->type = SGML_TOKEN_INCOMPLETE;
|
||||||
|
set_dom_string(&token->string, scanner->position, left);
|
||||||
|
|
||||||
|
/* Stop the scanning. */
|
||||||
|
scanner->position = scanner->end;
|
||||||
|
}
|
||||||
|
|
||||||
/* Text token scanning */
|
/* Text token scanning */
|
||||||
|
|
||||||
@ -119,6 +137,8 @@ scan_sgml_text_token(struct dom_scanner *scanner, struct dom_scanner_token *toke
|
|||||||
token->string.string = string++;
|
token->string.string = string++;
|
||||||
|
|
||||||
if (first_char == '&') {
|
if (first_char == '&') {
|
||||||
|
int complete = 0;
|
||||||
|
|
||||||
if (is_sgml_entity(*string)) {
|
if (is_sgml_entity(*string)) {
|
||||||
scan_sgml(scanner, string, SGML_CHAR_ENTITY);
|
scan_sgml(scanner, string, SGML_CHAR_ENTITY);
|
||||||
type = SGML_TOKEN_ENTITY;
|
type = SGML_TOKEN_ENTITY;
|
||||||
@ -128,13 +148,24 @@ scan_sgml_text_token(struct dom_scanner *scanner, struct dom_scanner_token *toke
|
|||||||
|
|
||||||
foreach_sgml_cdata (scanner, string) {
|
foreach_sgml_cdata (scanner, string) {
|
||||||
if (*string == ';') {
|
if (*string == ';') {
|
||||||
|
complete = 1;
|
||||||
string++;
|
string++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We want the biggest possible text token. */
|
||||||
|
if (check_sgml_incomplete(scanner, string) && !complete) {
|
||||||
|
set_sgml_incomplete(scanner, token);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (is_sgml_space(first_char)) {
|
if (is_sgml_space(first_char)) {
|
||||||
|
if (scanner->count_lines
|
||||||
|
&& is_sgml_newline(first_char))
|
||||||
|
scanner->lineno++;
|
||||||
|
|
||||||
skip_sgml_space(scanner, &string);
|
skip_sgml_space(scanner, &string);
|
||||||
type = string < scanner->end && is_sgml_text(*string)
|
type = string < scanner->end && is_sgml_text(*string)
|
||||||
? SGML_TOKEN_TEXT : SGML_TOKEN_SPACE;
|
? SGML_TOKEN_TEXT : SGML_TOKEN_SPACE;
|
||||||
@ -142,11 +173,24 @@ scan_sgml_text_token(struct dom_scanner *scanner, struct dom_scanner_token *toke
|
|||||||
type = SGML_TOKEN_TEXT;
|
type = SGML_TOKEN_TEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (scanner->count_lines) {
|
||||||
|
foreach_sgml_cdata (scanner, string) {
|
||||||
|
if (is_sgml_newline(*string))
|
||||||
|
scanner->lineno++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
foreach_sgml_cdata (scanner, string) {
|
foreach_sgml_cdata (scanner, string) {
|
||||||
/* m33p */;
|
/* m33p */;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We want the biggest possible text token. */
|
||||||
|
if (check_sgml_incomplete(scanner, string)) {
|
||||||
|
set_sgml_incomplete(scanner, token);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
token->type = type;
|
token->type = type;
|
||||||
token->string.length = real_length >= 0 ? real_length : string - token->string.string;
|
token->string.length = real_length >= 0 ? real_length : string - token->string.string;
|
||||||
token->precedence = get_sgml_precedence(type);
|
token->precedence = get_sgml_precedence(type);
|
||||||
@ -226,7 +270,8 @@ skip_sgml(struct dom_scanner *scanner, unsigned char **string, unsigned char ski
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
skip_sgml_comment(struct dom_scanner *scanner, unsigned char **string)
|
skip_sgml_comment(struct dom_scanner *scanner, unsigned char **string,
|
||||||
|
int *possibly_incomplete)
|
||||||
{
|
{
|
||||||
unsigned char *pos = *string;
|
unsigned char *pos = *string;
|
||||||
int length = 0;
|
int length = 0;
|
||||||
@ -238,6 +283,7 @@ skip_sgml_comment(struct dom_scanner *scanner, unsigned char **string)
|
|||||||
* preceeding '-'. */
|
* preceeding '-'. */
|
||||||
if (pos[-2] == '-' && pos[-1] == '-' && &pos[-2] >= *string) {
|
if (pos[-2] == '-' && pos[-1] == '-' && &pos[-2] >= *string) {
|
||||||
length = pos - *string - 2;
|
length = pos - *string - 2;
|
||||||
|
*possibly_incomplete = 0;
|
||||||
pos++;
|
pos++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -245,6 +291,9 @@ skip_sgml_comment(struct dom_scanner *scanner, unsigned char **string)
|
|||||||
|
|
||||||
if (!pos) {
|
if (!pos) {
|
||||||
pos = scanner->end;
|
pos = scanner->end;
|
||||||
|
/* The token is incomplete but set the length to handle tag
|
||||||
|
* tag soup graciously. */
|
||||||
|
*possibly_incomplete = 1;
|
||||||
length = pos - *string;
|
length = pos - *string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,7 +302,8 @@ skip_sgml_comment(struct dom_scanner *scanner, unsigned char **string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
skip_sgml_cdata_section(struct dom_scanner *scanner, unsigned char **string)
|
skip_sgml_cdata_section(struct dom_scanner *scanner, unsigned char **string,
|
||||||
|
int *possibly_incomplete)
|
||||||
{
|
{
|
||||||
unsigned char *pos = *string;
|
unsigned char *pos = *string;
|
||||||
int length = 0;
|
int length = 0;
|
||||||
@ -263,6 +313,7 @@ skip_sgml_cdata_section(struct dom_scanner *scanner, unsigned char **string)
|
|||||||
* are supposed to have '<![CDATA[' before this is called. */
|
* are supposed to have '<![CDATA[' before this is called. */
|
||||||
if (pos[-2] == ']' && pos[-1] == ']') {
|
if (pos[-2] == ']' && pos[-1] == ']') {
|
||||||
length = pos - *string - 2;
|
length = pos - *string - 2;
|
||||||
|
*possibly_incomplete = 0;
|
||||||
pos++;
|
pos++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -270,6 +321,9 @@ skip_sgml_cdata_section(struct dom_scanner *scanner, unsigned char **string)
|
|||||||
|
|
||||||
if (!pos) {
|
if (!pos) {
|
||||||
pos = scanner->end;
|
pos = scanner->end;
|
||||||
|
/* The token is incomplete but set the length to handle tag
|
||||||
|
* soup graciously. */
|
||||||
|
*possibly_incomplete = 1;
|
||||||
length = pos - *string;
|
length = pos - *string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,6 +342,7 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
|||||||
unsigned char first_char = *string;
|
unsigned char first_char = *string;
|
||||||
enum sgml_token_type type = SGML_TOKEN_GARBAGE;
|
enum sgml_token_type type = SGML_TOKEN_GARBAGE;
|
||||||
int real_length = -1;
|
int real_length = -1;
|
||||||
|
int possibly_incomplete = 1;
|
||||||
|
|
||||||
token->string.string = string++;
|
token->string.string = string++;
|
||||||
|
|
||||||
@ -302,6 +357,9 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
|||||||
type = SGML_TOKEN_TAG_END;
|
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;
|
||||||
|
|
||||||
} else if (is_sgml_ident(*string)) {
|
} else if (is_sgml_ident(*string)) {
|
||||||
token->string.string = string;
|
token->string.string = string;
|
||||||
scan_sgml(scanner, string, SGML_CHAR_IDENT);
|
scan_sgml(scanner, string, SGML_CHAR_IDENT);
|
||||||
@ -312,7 +370,16 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
|||||||
if (*string == '>') {
|
if (*string == '>') {
|
||||||
type = SGML_TOKEN_ELEMENT;
|
type = SGML_TOKEN_ELEMENT;
|
||||||
string++;
|
string++;
|
||||||
|
|
||||||
|
/* We found the end. */
|
||||||
|
possibly_incomplete = 0;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
/* Was any space skipped? */
|
||||||
|
if (is_sgml_space(string[-1])) {
|
||||||
|
/* We found the end. */
|
||||||
|
possibly_incomplete = 0;
|
||||||
|
}
|
||||||
scanner->state = SGML_STATE_ELEMENT;
|
scanner->state = SGML_STATE_ELEMENT;
|
||||||
type = SGML_TOKEN_ELEMENT_BEGIN;
|
type = SGML_TOKEN_ELEMENT_BEGIN;
|
||||||
}
|
}
|
||||||
@ -330,7 +397,8 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
|||||||
string += 2;
|
string += 2;
|
||||||
type = SGML_TOKEN_NOTATION_COMMENT;
|
type = SGML_TOKEN_NOTATION_COMMENT;
|
||||||
token->string.string = string;
|
token->string.string = string;
|
||||||
real_length = skip_sgml_comment(scanner, &string);
|
real_length = skip_sgml_comment(scanner, &string,
|
||||||
|
&possibly_incomplete);
|
||||||
assert(real_length >= 0);
|
assert(real_length >= 0);
|
||||||
|
|
||||||
} else if (string + 6 < scanner->end
|
} else if (string + 6 < scanner->end
|
||||||
@ -339,13 +407,17 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
|||||||
string += 7;
|
string += 7;
|
||||||
type = SGML_TOKEN_CDATA_SECTION;
|
type = SGML_TOKEN_CDATA_SECTION;
|
||||||
token->string.string = string;
|
token->string.string = string;
|
||||||
real_length = skip_sgml_cdata_section(scanner, &string);
|
real_length = skip_sgml_cdata_section(scanner, &string,
|
||||||
|
&possibly_incomplete);
|
||||||
assert(real_length >= 0);
|
assert(real_length >= 0);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
skip_sgml_space(scanner, &string);
|
skip_sgml_space(scanner, &string);
|
||||||
type = map_dom_scanner_string(scanner, ident, string, base);
|
type = map_dom_scanner_string(scanner, ident, string, base);
|
||||||
skip_sgml(scanner, &string, '>', 0);
|
if (skip_sgml(scanner, &string, '>', 0)) {
|
||||||
|
/* We found the end. */
|
||||||
|
possibly_incomplete = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (*string == '?') {
|
} else if (*string == '?') {
|
||||||
@ -361,6 +433,14 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
|||||||
|
|
||||||
scanner->state = SGML_STATE_PROC_INST;
|
scanner->state = SGML_STATE_PROC_INST;
|
||||||
|
|
||||||
|
real_length = string - token->string.string;
|
||||||
|
skip_sgml_space(scanner, &string);
|
||||||
|
|
||||||
|
if (is_sgml_space(string[-1])) {
|
||||||
|
/* We found the end. */
|
||||||
|
possibly_incomplete = 0;
|
||||||
|
}
|
||||||
|
|
||||||
} else if (*string == '/') {
|
} else if (*string == '/') {
|
||||||
string++;
|
string++;
|
||||||
skip_sgml_space(scanner, &string);
|
skip_sgml_space(scanner, &string);
|
||||||
@ -371,12 +451,18 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
|||||||
real_length = string - token->string.string;
|
real_length = string - token->string.string;
|
||||||
|
|
||||||
type = SGML_TOKEN_ELEMENT_END;
|
type = SGML_TOKEN_ELEMENT_END;
|
||||||
skip_sgml(scanner, &string, '>', 1);
|
if (skip_sgml(scanner, &string, '>', 1)) {
|
||||||
|
/* We found the end. */
|
||||||
|
possibly_incomplete = 0;
|
||||||
|
}
|
||||||
|
|
||||||
} else if (*string == '>') {
|
} else if (*string == '>') {
|
||||||
string++;
|
string++;
|
||||||
real_length = 0;
|
real_length = 0;
|
||||||
type = SGML_TOKEN_ELEMENT_END;
|
type = SGML_TOKEN_ELEMENT_END;
|
||||||
|
|
||||||
|
/* We found the end. */
|
||||||
|
possibly_incomplete = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type != SGML_TOKEN_GARBAGE)
|
if (type != SGML_TOKEN_GARBAGE)
|
||||||
@ -384,15 +470,28 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* Alien < > stuff so ignore it */
|
/* Alien < > stuff so ignore it */
|
||||||
skip_sgml(scanner, &string, '>', 0);
|
if (skip_sgml(scanner, &string, '>', 0)) {
|
||||||
|
/* We found the end. */
|
||||||
|
possibly_incomplete = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (first_char == '=') {
|
} else if (first_char == '=') {
|
||||||
type = '=';
|
type = '=';
|
||||||
|
/* We found the end. */
|
||||||
|
possibly_incomplete = 0;
|
||||||
|
|
||||||
} else if (first_char == '?' || first_char == '>') {
|
} else if (first_char == '?' || first_char == '>') {
|
||||||
if (first_char == '?') {
|
if (first_char == '?') {
|
||||||
skip_sgml(scanner, &string, '>', 0);
|
if (skip_sgml(scanner, &string, '>', 0)) {
|
||||||
|
/* We found the end. */
|
||||||
|
possibly_incomplete = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert(first_char == '>');
|
||||||
|
|
||||||
|
/* We found the end. */
|
||||||
|
possibly_incomplete = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
type = SGML_TOKEN_TAG_END;
|
type = SGML_TOKEN_TAG_END;
|
||||||
@ -400,17 +499,33 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
|||||||
scanner->state = SGML_STATE_TEXT;
|
scanner->state = SGML_STATE_TEXT;
|
||||||
|
|
||||||
} else if (first_char == '/') {
|
} else if (first_char == '/') {
|
||||||
|
/* We allow '/' inside elements and only consider it as an end
|
||||||
|
* tag if immediately preceeds the '>' char. This is to allow
|
||||||
|
*
|
||||||
|
* '<form action=/ >' where '/' is part of a path and
|
||||||
|
* '<form action=a />' where '/>' is truely a tag end
|
||||||
|
*
|
||||||
|
* For stricter parsing we should always require attribute
|
||||||
|
* values to be quoted.
|
||||||
|
*/
|
||||||
if (*string == '>') {
|
if (*string == '>') {
|
||||||
string++;
|
string++;
|
||||||
real_length = 0;
|
real_length = 0;
|
||||||
type = SGML_TOKEN_ELEMENT_EMPTY_END;
|
type = SGML_TOKEN_ELEMENT_EMPTY_END;
|
||||||
assert(scanner->state == SGML_STATE_ELEMENT);
|
assert(scanner->state == SGML_STATE_ELEMENT);
|
||||||
scanner->state = SGML_STATE_TEXT;
|
scanner->state = SGML_STATE_TEXT;
|
||||||
|
|
||||||
|
/* We found the end. */
|
||||||
|
possibly_incomplete = 0;
|
||||||
|
|
||||||
} else if (is_sgml_attribute(*string)) {
|
} else if (is_sgml_attribute(*string)) {
|
||||||
scan_sgml_attribute(scanner, string);
|
scan_sgml_attribute(scanner, string);
|
||||||
type = SGML_TOKEN_ATTRIBUTE;
|
type = SGML_TOKEN_ATTRIBUTE;
|
||||||
if (string[-1] == '/' && string[0] == '>')
|
if (string[-1] == '/' && string[0] == '>') {
|
||||||
string--;
|
string--;
|
||||||
|
/* We found the end. */
|
||||||
|
possibly_incomplete = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (isquote(first_char)) {
|
} else if (isquote(first_char)) {
|
||||||
@ -422,6 +537,10 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
|||||||
real_length = string_end - token->string.string;
|
real_length = string_end - token->string.string;
|
||||||
string = string_end + 1;
|
string = string_end + 1;
|
||||||
type = SGML_TOKEN_STRING;
|
type = SGML_TOKEN_STRING;
|
||||||
|
|
||||||
|
/* We found the end. */
|
||||||
|
possibly_incomplete = 0;
|
||||||
|
|
||||||
} else if (is_sgml_attribute(*string)) {
|
} else if (is_sgml_attribute(*string)) {
|
||||||
token->string.string++;
|
token->string.string++;
|
||||||
scan_sgml_attribute(scanner, string);
|
scan_sgml_attribute(scanner, string);
|
||||||
@ -437,10 +556,18 @@ scan_sgml_element_token(struct dom_scanner *scanner, struct dom_scanner_token *t
|
|||||||
if (is_sgml_attribute(*string)) {
|
if (is_sgml_attribute(*string)) {
|
||||||
scan_sgml_attribute(scanner, string);
|
scan_sgml_attribute(scanner, string);
|
||||||
type = SGML_TOKEN_ATTRIBUTE;
|
type = SGML_TOKEN_ATTRIBUTE;
|
||||||
if (string[-1] == '/' && string[0] == '>')
|
if (string[-1] == '/' && string[0] == '>') {
|
||||||
|
/* We found the end. */
|
||||||
|
possibly_incomplete = 0;
|
||||||
string--;
|
string--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (possibly_incomplete && check_sgml_incomplete(scanner, string)) {
|
||||||
|
set_sgml_incomplete(scanner, token);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
token->type = type;
|
token->type = type;
|
||||||
token->string.length = real_length >= 0 ? real_length : string - token->string.string;
|
token->string.length = real_length >= 0 ? real_length : string - token->string.string;
|
||||||
@ -455,6 +582,8 @@ static inline void
|
|||||||
scan_sgml_proc_inst_token(struct dom_scanner *scanner, struct dom_scanner_token *token)
|
scan_sgml_proc_inst_token(struct dom_scanner *scanner, struct dom_scanner_token *token)
|
||||||
{
|
{
|
||||||
unsigned char *string = scanner->position;
|
unsigned char *string = scanner->position;
|
||||||
|
/* The length can be empty for '<??>'. */
|
||||||
|
size_t length = -1;
|
||||||
|
|
||||||
token->string.string = string;
|
token->string.string = string;
|
||||||
|
|
||||||
@ -464,14 +593,23 @@ scan_sgml_proc_inst_token(struct dom_scanner *scanner, struct dom_scanner_token
|
|||||||
for ( ; (string = skip_sgml_chars(scanner, string, '>')); string++) {
|
for ( ; (string = skip_sgml_chars(scanner, string, '>')); string++) {
|
||||||
if (string[-1] == '?') {
|
if (string[-1] == '?') {
|
||||||
string++;
|
string++;
|
||||||
|
length = string - token->string.string - 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string) string = scanner->end;
|
if (!string) {
|
||||||
|
/* Makes the next succeed when checking for incompletion. */
|
||||||
|
string = scanner->end;
|
||||||
|
|
||||||
|
if (check_sgml_incomplete(scanner, string)) {
|
||||||
|
set_sgml_incomplete(scanner, token);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
token->type = SGML_TOKEN_PROCESS_DATA;
|
token->type = SGML_TOKEN_PROCESS_DATA;
|
||||||
token->string.length = string - token->string.string - 2;
|
token->string.length = length >= 0 ? length : string - token->string.string;
|
||||||
token->precedence = get_sgml_precedence(token->type);
|
token->precedence = get_sgml_precedence(token->type);
|
||||||
scanner->position = string;
|
scanner->position = string;
|
||||||
scanner->state = SGML_STATE_TEXT;
|
scanner->state = SGML_STATE_TEXT;
|
||||||
@ -510,7 +648,6 @@ scan_sgml_tokens(struct dom_scanner *scanner)
|
|||||||
scan_sgml_text_token(scanner, current);
|
scan_sgml_text_token(scanner, current);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
skip_sgml_space(scanner, &scanner->position);
|
|
||||||
scan_sgml_proc_inst_token(scanner, current);
|
scan_sgml_proc_inst_token(scanner, current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,10 @@ enum sgml_token_type {
|
|||||||
/* A special token for unrecognized strings */
|
/* A special token for unrecognized strings */
|
||||||
SGML_TOKEN_GARBAGE,
|
SGML_TOKEN_GARBAGE,
|
||||||
|
|
||||||
|
/* A special token for marking that it is assummed that the token is
|
||||||
|
* not complete. Only meaningful if scanner->complete is incomplete. */
|
||||||
|
SGML_TOKEN_INCOMPLETE,
|
||||||
|
|
||||||
/* Token type used internally when scanning to signal that the token
|
/* Token type used internally when scanning to signal that the token
|
||||||
* should not be recorded in the scanners token table. */
|
* should not be recorded in the scanners token table. */
|
||||||
SGML_TOKEN_SKIP,
|
SGML_TOKEN_SKIP,
|
||||||
|
@ -213,7 +213,7 @@ pop_dom_node(struct dom_stack *stack)
|
|||||||
|
|
||||||
call_dom_stack_callbacks(stack, state, DOM_STACK_POP);
|
call_dom_stack_callbacks(stack, state, DOM_STACK_POP);
|
||||||
|
|
||||||
if (!(stack->flags & DOM_STACK_KEEP_NODES))
|
if (stack->flags & DOM_STACK_FLAG_FREE_NODES)
|
||||||
done_dom_node(state->node);
|
done_dom_node(state->node);
|
||||||
|
|
||||||
stack->depth--;
|
stack->depth--;
|
||||||
|
@ -48,8 +48,10 @@ struct dom_stack_context {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum dom_stack_flag {
|
enum dom_stack_flag {
|
||||||
/* Keep nodes when popping them or call done_dom_node() on them. */
|
DOM_STACK_FLAG_NONE = 0,
|
||||||
DOM_STACK_KEEP_NODES = 1,
|
|
||||||
|
/* Free nodes when popping them by calling done_dom_node(). */
|
||||||
|
DOM_STACK_FLAG_FREE_NODES = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The DOM stack is a convenient way to traverse DOM trees. Also it
|
/* The DOM stack is a convenient way to traverse DOM trees. Also it
|
||||||
|
@ -11,33 +11,9 @@ TESTDEPS = \
|
|||||||
$(top_builddir)/src/util/error.o \
|
$(top_builddir)/src/util/error.o \
|
||||||
$(top_builddir)/src/osdep/stub.o \
|
$(top_builddir)/src/osdep/stub.o \
|
||||||
$(top_builddir)/src/util/hash.o \
|
$(top_builddir)/src/util/hash.o \
|
||||||
$(top_builddir)/src/util/memdebug.o \
|
|
||||||
$(top_builddir)/src/util/string.o \
|
$(top_builddir)/src/util/string.o \
|
||||||
$(top_builddir)/src/util/memory.o
|
$(top_builddir)/src/util/memory.o
|
||||||
|
|
||||||
$(TEST_PROGS): $(TESTDEPS) $$@.o
|
TESTDEPS-$(CONFIG_DEBUG) += $(top_builddir)/src/util/memdebug.o \
|
||||||
$(call cmd,link)
|
|
||||||
|
|
||||||
TESTS = $(wildcard test-*)
|
|
||||||
|
|
||||||
$(TESTS): $(TEST_PROGS)
|
|
||||||
@echo "*** $@ ***"; $(call shellquote,$(SHELL)) $@ $(TEST_OPTS)
|
|
||||||
|
|
||||||
test: $(TESTS)
|
|
||||||
|
|
||||||
clean-local:
|
|
||||||
@rm -fr trash
|
|
||||||
|
|
||||||
CLEAN += $(TEST_PROGS) $(patsubst %,%.o,$(TEST_PROGS))
|
|
||||||
|
|
||||||
.PHONY: $(TESTS)
|
|
||||||
.NOPARALLEL:
|
|
||||||
|
|
||||||
include $(top_srcdir)/Makefile.lib
|
include $(top_srcdir)/Makefile.lib
|
||||||
|
|
||||||
# Shell quote;
|
|
||||||
# Result of this needs to be placed inside ''
|
|
||||||
# XXX: Placed here because Vim cannot highlight things right afterwards
|
|
||||||
shq = $(subst ','\'',$(1))
|
|
||||||
# This has surrounding ''
|
|
||||||
shellquote = '$(call shq,$(1))'
|
|
||||||
|
@ -16,6 +16,24 @@
|
|||||||
#include "dom/stack.h"
|
#include "dom/stack.h"
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int number_of_lines = 0;
|
||||||
|
|
||||||
|
static int
|
||||||
|
update_number_of_lines(struct dom_stack *stack)
|
||||||
|
{
|
||||||
|
struct sgml_parser *parser = stack->contexts[0]->data;
|
||||||
|
int lines;
|
||||||
|
|
||||||
|
if (!(parser->flags & SGML_PARSER_COUNT_LINES))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
lines = get_sgml_parser_line_number(parser);
|
||||||
|
if (number_of_lines < lines)
|
||||||
|
number_of_lines = lines;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Print the string in a compressed form: a single line with newlines etc.
|
/* Print the string in a compressed form: a single line with newlines etc.
|
||||||
* replaced with "\\n" sequence. */
|
* replaced with "\\n" sequence. */
|
||||||
static void
|
static void
|
||||||
@ -72,14 +90,24 @@ static unsigned char indent_string[] =
|
|||||||
#define get_indent_offset(stack) \
|
#define get_indent_offset(stack) \
|
||||||
(((stack)->depth < sizeof(indent_string)/2 ? (stack)->depth * 2 : sizeof(indent_string)) - 2)
|
(((stack)->depth < sizeof(indent_string)/2 ? (stack)->depth * 2 : sizeof(indent_string)) - 2)
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_indent(struct dom_stack *stack)
|
||||||
|
{
|
||||||
|
printf("%.*s", get_indent_offset(stack), indent_string);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sgml_parser_test_tree(struct dom_stack *stack, struct dom_node *node, void *data)
|
sgml_parser_test_tree(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||||
{
|
{
|
||||||
struct dom_string *value = &node->string;
|
struct dom_string *value = &node->string;
|
||||||
struct dom_string *name = get_dom_node_name(node);
|
struct dom_string *name = get_dom_node_name(node);
|
||||||
|
|
||||||
printf("%.*s%.*s: %.*s\n",
|
/* Always print the URI for identification. */
|
||||||
get_indent_offset(stack), indent_string,
|
update_number_of_lines(stack);
|
||||||
|
|
||||||
|
print_indent(stack);
|
||||||
|
printf("%.*s: %.*s\n",
|
||||||
name->length, name->string,
|
name->length, name->string,
|
||||||
value->length, value->string);
|
value->length, value->string);
|
||||||
}
|
}
|
||||||
@ -92,12 +120,16 @@ sgml_parser_test_id_leaf(struct dom_stack *stack, struct dom_node *node, void *d
|
|||||||
|
|
||||||
assert(node);
|
assert(node);
|
||||||
|
|
||||||
|
if (update_number_of_lines(stack))
|
||||||
|
return;
|
||||||
|
|
||||||
name = get_dom_node_name(node);
|
name = get_dom_node_name(node);
|
||||||
id = get_dom_node_type_name(node->type);
|
id = get_dom_node_type_name(node->type);
|
||||||
|
|
||||||
printf("%.*s%.*s: %.*s -> ",
|
print_indent(stack);
|
||||||
get_indent_offset(stack), indent_string,
|
printf("%.*s: %.*s -> ",
|
||||||
id->length, id->string, name->length, name->string);
|
id->length, id->string,
|
||||||
|
name->length, name->string);
|
||||||
print_dom_node_value(node);
|
print_dom_node_value(node);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
@ -109,10 +141,13 @@ sgml_parser_test_leaf(struct dom_stack *stack, struct dom_node *node, void *data
|
|||||||
|
|
||||||
assert(node);
|
assert(node);
|
||||||
|
|
||||||
|
if (update_number_of_lines(stack))
|
||||||
|
return;
|
||||||
|
|
||||||
name = get_dom_node_name(node);
|
name = get_dom_node_name(node);
|
||||||
|
|
||||||
printf("%.*s%.*s: ",
|
print_indent(stack);
|
||||||
get_indent_offset(stack), indent_string,
|
printf("%.*s: ",
|
||||||
name->length, name->string);
|
name->length, name->string);
|
||||||
print_dom_node_value(node);
|
print_dom_node_value(node);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@ -126,14 +161,27 @@ sgml_parser_test_branch(struct dom_stack *stack, struct dom_node *node, void *da
|
|||||||
|
|
||||||
assert(node);
|
assert(node);
|
||||||
|
|
||||||
|
if (update_number_of_lines(stack))
|
||||||
|
return;
|
||||||
|
|
||||||
name = get_dom_node_name(node);
|
name = get_dom_node_name(node);
|
||||||
id = get_dom_node_type_name(node->type);
|
id = get_dom_node_type_name(node->type);
|
||||||
|
|
||||||
printf("%.*s%.*s: %.*s\n",
|
print_indent(stack);
|
||||||
get_indent_offset(stack), indent_string,
|
printf("%.*s: %.*s\n",
|
||||||
id->length, id->string, name->length, name->string);
|
id->length, id->string, name->length, name->string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sgml_parser_test_end(struct dom_stack *stack, struct dom_node *node, void *data)
|
||||||
|
{
|
||||||
|
struct sgml_parser *parser = stack->contexts[0]->data;
|
||||||
|
|
||||||
|
if (parser->flags & SGML_PARSER_COUNT_LINES) {
|
||||||
|
printf("%d\n", number_of_lines);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct dom_stack_context_info sgml_parser_test_context_info = {
|
struct dom_stack_context_info sgml_parser_test_context_info = {
|
||||||
/* Object size: */ 0,
|
/* Object size: */ 0,
|
||||||
/* Push: */
|
/* Push: */
|
||||||
@ -163,7 +211,7 @@ struct dom_stack_context_info sgml_parser_test_context_info = {
|
|||||||
/* DOM_NODE_ENTITY */ NULL,
|
/* DOM_NODE_ENTITY */ NULL,
|
||||||
/* DOM_NODE_PROC_INSTRUCTION */ NULL,
|
/* DOM_NODE_PROC_INSTRUCTION */ NULL,
|
||||||
/* DOM_NODE_COMMENT */ NULL,
|
/* DOM_NODE_COMMENT */ NULL,
|
||||||
/* DOM_NODE_DOCUMENT */ NULL,
|
/* DOM_NODE_DOCUMENT */ sgml_parser_test_end,
|
||||||
/* DOM_NODE_DOCUMENT_TYPE */ NULL,
|
/* DOM_NODE_DOCUMENT_TYPE */ NULL,
|
||||||
/* DOM_NODE_DOCUMENT_FRAGMENT */ NULL,
|
/* DOM_NODE_DOCUMENT_FRAGMENT */ NULL,
|
||||||
/* DOM_NODE_NOTATION */ NULL,
|
/* DOM_NODE_NOTATION */ NULL,
|
||||||
@ -188,9 +236,11 @@ void die(const char *msg, ...)
|
|||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct dom_node *root;
|
|
||||||
struct sgml_parser *parser;
|
struct sgml_parser *parser;
|
||||||
enum sgml_document_type doctype = SGML_DOCTYPE_HTML;
|
enum sgml_document_type doctype = SGML_DOCTYPE_HTML;
|
||||||
|
enum sgml_parser_flag flags = 0;
|
||||||
|
enum sgml_parser_code code = 0;
|
||||||
|
int complete = 1;
|
||||||
struct dom_string uri = INIT_DOM_STRING("dom://test", -1);
|
struct dom_string uri = INIT_DOM_STRING("dom://test", -1);
|
||||||
struct dom_string source = INIT_DOM_STRING("(no source)", -1);
|
struct dom_string source = INIT_DOM_STRING("(no source)", -1);
|
||||||
int i;
|
int i;
|
||||||
@ -227,6 +277,13 @@ main(int argc, char *argv[])
|
|||||||
set_dom_string(&source, argv[i], strlen(argv[i]));
|
set_dom_string(&source, argv[i], strlen(argv[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (!strcmp(arg, "print-lines")) {
|
||||||
|
flags |= SGML_PARSER_COUNT_LINES;
|
||||||
|
|
||||||
|
} else if (!strcmp(arg, "incomplete")) {
|
||||||
|
flags |= SGML_PARSER_INCREMENTAL;
|
||||||
|
complete = 0;
|
||||||
|
|
||||||
} else if (!strcmp(arg, "help")) {
|
} else if (!strcmp(arg, "help")) {
|
||||||
die(NULL);
|
die(NULL);
|
||||||
|
|
||||||
@ -235,22 +292,26 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
parser = init_sgml_parser(SGML_PARSER_STREAM, doctype, &uri);
|
parser = init_sgml_parser(SGML_PARSER_STREAM, doctype, &uri, flags);
|
||||||
if (!parser) return 1;
|
if (!parser) return 1;
|
||||||
|
|
||||||
add_dom_stack_context(&parser->stack, NULL, &sgml_parser_test_context_info);
|
add_dom_stack_context(&parser->stack, NULL, &sgml_parser_test_context_info);
|
||||||
|
|
||||||
root = parse_sgml(parser, &source);
|
code = parse_sgml(parser, &source, complete);
|
||||||
if (root) {
|
if (parser->root) {
|
||||||
assert(parser->stack.depth == 1);
|
size_t root_offset = parser->stack.depth - 1;
|
||||||
|
|
||||||
|
assert(!complete || root_offset == 0);
|
||||||
|
|
||||||
|
get_dom_stack_state(&parser->stack, root_offset)->immutable = 0;
|
||||||
|
|
||||||
get_dom_stack_top(&parser->stack)->immutable = 0;
|
|
||||||
/* For SGML_PARSER_STREAM this will free the DOM
|
/* For SGML_PARSER_STREAM this will free the DOM
|
||||||
* root node. */
|
* root node. */
|
||||||
|
while (!dom_stack_is_empty(&parser->stack))
|
||||||
pop_dom_node(&parser->stack);
|
pop_dom_node(&parser->stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
done_sgml_parser(parser);
|
done_sgml_parser(parser);
|
||||||
|
|
||||||
return 0;
|
return code;
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,12 @@ This test runs very basic features, like checking that nodes are placed
|
|||||||
correctly in the DOM tree.
|
correctly in the DOM tree.
|
||||||
'
|
'
|
||||||
|
|
||||||
. ./libtest
|
. "$TEST_LIB"
|
||||||
|
|
||||||
test_output_equals () {
|
test_output_equals () {
|
||||||
desc="$1"
|
desc="$1"; shift
|
||||||
src="$2"
|
src="$1"; shift
|
||||||
out="$3"
|
out="$1"; shift
|
||||||
|
|
||||||
URI="test:$(echo "$desc" | sed '
|
URI="test:$(echo "$desc" | sed '
|
||||||
s/^[ \t]*\[[^]]*\][ \t]*//;
|
s/^[ \t]*\[[^]]*\][ \t]*//;
|
||||||
@ -24,11 +24,27 @@ test_output_equals () {
|
|||||||
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/;
|
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/;
|
||||||
s/[^a-zA-Z0-9-]//g;')"
|
s/[^a-zA-Z0-9-]//g;')"
|
||||||
|
|
||||||
sgml-parser --uri "$URI" --src "$src" | sed 's/^ //' > output
|
sgml-parser --uri "$URI" --src "$src" $@ | sed 's/^ //' > output
|
||||||
echo "#document: $URI" > expected
|
echo "#document: $URI" > expected
|
||||||
echo "$out" | sed -n '2,$p' >> expected
|
echo "$out" | sed -n '2,$p' >> expected
|
||||||
|
|
||||||
test_expect_success "$desc" 'cmp -b output expected'
|
test_expect_success "$desc" 'cmp output expected'
|
||||||
|
}
|
||||||
|
|
||||||
|
test_expect_incomplete () {
|
||||||
|
desc="$1"; shift
|
||||||
|
src="$1"; shift
|
||||||
|
|
||||||
|
URI="test:$(echo "$desc" | sed '
|
||||||
|
s/^[ \t]*\[[^]]*\][ \t]*//;
|
||||||
|
s/[:., \t][:., \t]*/-/g;
|
||||||
|
s/_/-/g;
|
||||||
|
# *cough*
|
||||||
|
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/;
|
||||||
|
s/[^a-zA-Z0-9-]//g;')"
|
||||||
|
|
||||||
|
test_expect_code 1 "$desc" \
|
||||||
|
"sgml-parser --uri '$URI' --src '$src' --incomplete"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -55,6 +71,16 @@ element: root
|
|||||||
element: child3
|
element: child3
|
||||||
#text: a'
|
#text: a'
|
||||||
|
|
||||||
|
test_output_equals \
|
||||||
|
'Parse tag soup elements.' \
|
||||||
|
'<parent attr="value" <child:1></><child:2</>a</parent>' \
|
||||||
|
'
|
||||||
|
element: parent
|
||||||
|
attribute: attr -> value
|
||||||
|
element: child:1
|
||||||
|
element: child:2
|
||||||
|
#text: a'
|
||||||
|
|
||||||
test_output_equals \
|
test_output_equals \
|
||||||
'Parse an enclosed comment.' \
|
'Parse an enclosed comment.' \
|
||||||
'<root><!-- Hello World! --></root>' \
|
'<root><!-- Hello World! --></root>' \
|
||||||
@ -63,7 +89,7 @@ element: root
|
|||||||
#comment: Hello World! '
|
#comment: Hello World! '
|
||||||
|
|
||||||
test_output_equals \
|
test_output_equals \
|
||||||
'Parse comment combinations.' \
|
'Parse comment combinations. (I)' \
|
||||||
'<root><!-- <!-- -- > --><!--foo--><!----></root>' \
|
'<root><!-- <!-- -- > --><!--foo--><!----></root>' \
|
||||||
'
|
'
|
||||||
element: root
|
element: root
|
||||||
@ -71,12 +97,29 @@ element: root
|
|||||||
#comment: foo
|
#comment: foo
|
||||||
#comment: '
|
#comment: '
|
||||||
|
|
||||||
|
test_output_equals \
|
||||||
|
'Parse comment combinations. (II).' \
|
||||||
|
'<! -- comment -->s<!-->-->t<!----->u' \
|
||||||
|
'
|
||||||
|
#comment: comment
|
||||||
|
#text: s
|
||||||
|
#comment: >
|
||||||
|
#text: t
|
||||||
|
#comment: -
|
||||||
|
#text: u'
|
||||||
|
|
||||||
test_output_equals \
|
test_output_equals \
|
||||||
'Parse bad comment.' \
|
'Parse bad comment.' \
|
||||||
'<!--->s' \
|
'<!--->s' \
|
||||||
'
|
'
|
||||||
#comment: ->s'
|
#comment: ->s'
|
||||||
|
|
||||||
|
test_output_equals \
|
||||||
|
'Parse empty notation.' \
|
||||||
|
'<!>s' \
|
||||||
|
'
|
||||||
|
#text: s'
|
||||||
|
|
||||||
test_output_equals \
|
test_output_equals \
|
||||||
'Parse an enclosed CDATA section.' \
|
'Parse an enclosed CDATA section.' \
|
||||||
'<root><![CDATA[...] ]>...]]></root>' \
|
'<root><![CDATA[...] ]>...]]></root>' \
|
||||||
@ -167,7 +210,7 @@ test_output_equals \
|
|||||||
'
|
'
|
||||||
proc-instruction: xml -> version="1.0" />
|
proc-instruction: xml -> version="1.0" />
|
||||||
attribute: version -> 1.0
|
attribute: version -> 1.0
|
||||||
proc-instruction: xml -> /'
|
proc-instruction: xml -> />-'
|
||||||
|
|
||||||
test_output_equals \
|
test_output_equals \
|
||||||
'Parse XML stylesheet processing instructions.' \
|
'Parse XML stylesheet processing instructions.' \
|
||||||
@ -220,4 +263,121 @@ element: root
|
|||||||
attribute: ns:attr -> value
|
attribute: ns:attr -> value
|
||||||
proc-instruction: target -> data'
|
proc-instruction: target -> data'
|
||||||
|
|
||||||
|
test_output_equals \
|
||||||
|
'Check line numbers. (I)' \
|
||||||
|
'<!-- line --> number <one />' \
|
||||||
|
'
|
||||||
|
1' \
|
||||||
|
--print-lines
|
||||||
|
|
||||||
|
test_output_equals \
|
||||||
|
'Check line numbers. (II)' \
|
||||||
|
'<
|
||||||
|
line:2
|
||||||
|
line:3
|
||||||
|
=
|
||||||
|
"line:5"
|
||||||
|
><?xml
|
||||||
|
line:7="..."
|
||||||
|
line:8
|
||||||
|
=
|
||||||
|
'\''...'\''></line:10>' \
|
||||||
|
'
|
||||||
|
10' \
|
||||||
|
--print-lines
|
||||||
|
|
||||||
|
test_output_equals \
|
||||||
|
'Check line numbers. (III)' \
|
||||||
|
'1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
5
|
||||||
|
6
|
||||||
|
7
|
||||||
|
8' \
|
||||||
|
'
|
||||||
|
8' \
|
||||||
|
--print-lines
|
||||||
|
|
||||||
|
test_expect_incomplete \
|
||||||
|
'Check incomplete comment. (I)' \
|
||||||
|
'<!-'
|
||||||
|
|
||||||
|
test_expect_incomplete \
|
||||||
|
'Check incomplete comment. (II)' \
|
||||||
|
'<!-- ... '
|
||||||
|
|
||||||
|
test_expect_incomplete \
|
||||||
|
'Check incomplete notation. (I)' \
|
||||||
|
'<!'
|
||||||
|
|
||||||
|
test_expect_incomplete \
|
||||||
|
'Check incomplete notation. (II)' \
|
||||||
|
'<!D'
|
||||||
|
|
||||||
|
test_expect_incomplete \
|
||||||
|
'Check incomplete cdata section. (I)' \
|
||||||
|
'<![CDATA[ ... '
|
||||||
|
|
||||||
|
test_expect_incomplete \
|
||||||
|
'Check incomplete cdata section. (II)' \
|
||||||
|
'<![CDAT'
|
||||||
|
|
||||||
|
test_expect_incomplete \
|
||||||
|
'Check incomplete element. (I)' \
|
||||||
|
'<elem...'
|
||||||
|
|
||||||
|
test_expect_incomplete \
|
||||||
|
'Check incomplete element. (II)' \
|
||||||
|
'<'
|
||||||
|
|
||||||
|
test_expect_incomplete \
|
||||||
|
'Check incomplete element end. (I)' \
|
||||||
|
'<a></a'
|
||||||
|
|
||||||
|
test_expect_incomplete \
|
||||||
|
'Check incomplete element end. (II)' \
|
||||||
|
'<a></'
|
||||||
|
|
||||||
|
test_expect_incomplete \
|
||||||
|
'Check incomplete attribute.' \
|
||||||
|
'<element attr...'
|
||||||
|
|
||||||
|
test_expect_incomplete \
|
||||||
|
'Check incomplete attribute value.' \
|
||||||
|
'<element attr=...'
|
||||||
|
|
||||||
|
test_expect_incomplete \
|
||||||
|
'Check incomplete attribute quoted value. (I)' \
|
||||||
|
'<element attr="...'
|
||||||
|
|
||||||
|
test_expect_incomplete \
|
||||||
|
'Check incomplete attribute quoted value. (II)' \
|
||||||
|
'<element attr='\''...'
|
||||||
|
|
||||||
|
test_expect_incomplete \
|
||||||
|
'Check incomplete processing instruction. (I)' \
|
||||||
|
'<?xml'
|
||||||
|
|
||||||
|
test_expect_incomplete \
|
||||||
|
'Check incomplete processing instruction. (II)' \
|
||||||
|
'<?xml attr...'
|
||||||
|
|
||||||
|
test_expect_incomplete \
|
||||||
|
'Check incomplete notation.' \
|
||||||
|
'<!DOCTYPE html PUBLIC ...'
|
||||||
|
|
||||||
|
test_expect_incomplete \
|
||||||
|
'Check incomplete reference. (I)' \
|
||||||
|
'�'
|
||||||
|
|
||||||
|
test_expect_incomplete \
|
||||||
|
'Check incomplete reference. (II)' \
|
||||||
|
'&'
|
||||||
|
|
||||||
|
test_expect_incomplete \
|
||||||
|
'Check incomplete text.' \
|
||||||
|
'plain text is always incomplete (if incomplete)'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
@ -85,7 +85,7 @@ struct entity { char *s; unicode_val_T c; } entities [1002] = {
|
|||||||
{ "Iogon", 0x012E }, /* LATIN CAPITAL LETTER I WITH OGONEK */
|
{ "Iogon", 0x012E }, /* LATIN CAPITAL LETTER I WITH OGONEK */
|
||||||
{ "Iota", 0x0399 }, /* GREEK CAPITAL LETTER IOTA */
|
{ "Iota", 0x0399 }, /* GREEK CAPITAL LETTER IOTA */
|
||||||
{ "Itilde", 0x0128 }, /* LATIN CAPITAL LETTER I WITH TILDE */
|
{ "Itilde", 0x0128 }, /* LATIN CAPITAL LETTER I WITH TILDE */
|
||||||
{"Iukcy", 0x0406}, /* CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN*/
|
{ "Iukcy", 0x0406 }, /* CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */
|
||||||
{ "Iuml", 0x00CF }, /* LATIN CAPITAL LETTER I WITH DIAERESIS */
|
{ "Iuml", 0x00CF }, /* LATIN CAPITAL LETTER I WITH DIAERESIS */
|
||||||
{ "Jcirc", 0x0134 }, /* LATIN CAPITAL LETTER J WITH CIRCUMFLEX */
|
{ "Jcirc", 0x0134 }, /* LATIN CAPITAL LETTER J WITH CIRCUMFLEX */
|
||||||
{ "Jcy", 0x0419 }, /* CYRILLIC CAPITAL LETTER SHORT I */
|
{ "Jcy", 0x0419 }, /* CYRILLIC CAPITAL LETTER SHORT I */
|
||||||
@ -166,7 +166,7 @@ struct entity { char *s; unicode_val_T c; } entities [1002] = {
|
|||||||
{ "Sub", 0x22D0 }, /* DOUBLE SUBSET */
|
{ "Sub", 0x22D0 }, /* DOUBLE SUBSET */
|
||||||
{ "Sup", 0x22D1 }, /* DOUBLE SUPERSET */
|
{ "Sup", 0x22D1 }, /* DOUBLE SUPERSET */
|
||||||
{ "THORN", 0x00DE }, /* LATIN CAPITAL LETTER THORN */
|
{ "THORN", 0x00DE }, /* LATIN CAPITAL LETTER THORN */
|
||||||
{"THgr", 0x0398}, /* GREEK CAPITAL LETTER THETA */
|
{ "THgr", 0x0398 }, /* GREEK CAPITAL LETTER THETA WITH TONOS */
|
||||||
{ "TSHcy", 0x040B }, /* CYRILLIC CAPITAL LETTER TSHE */
|
{ "TSHcy", 0x040B }, /* CYRILLIC CAPITAL LETTER TSHE */
|
||||||
{ "TScy", 0x0426 }, /* CYRILLIC CAPITAL LETTER TSE */
|
{ "TScy", 0x0426 }, /* CYRILLIC CAPITAL LETTER TSE */
|
||||||
{ "Tau", 0x03A4 }, /* GREEK CAPITAL LETTER TAU */
|
{ "Tau", 0x03A4 }, /* GREEK CAPITAL LETTER TAU */
|
||||||
@ -322,7 +322,7 @@ struct entity { char *s; unicode_val_T c; } entities [1002] = {
|
|||||||
{ "boxVH", 0x256C }, /* BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL */
|
{ "boxVH", 0x256C }, /* BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL */
|
||||||
{ "boxVL", 0x2563 }, /* BOX DRAWINGS DOUBLE VERTICAL AND LEFT */
|
{ "boxVL", 0x2563 }, /* BOX DRAWINGS DOUBLE VERTICAL AND LEFT */
|
||||||
{ "boxVR", 0x2560 }, /* BOX DRAWINGS DOUBLE VERTICAL AND RIGHT */
|
{ "boxVR", 0x2560 }, /* BOX DRAWINGS DOUBLE VERTICAL AND RIGHT */
|
||||||
{"boxVh", 0x256B}, /* BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SI*/
|
{ "boxVh", 0x256B }, /* BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE */
|
||||||
{ "boxVl", 0x2562 }, /* BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE */
|
{ "boxVl", 0x2562 }, /* BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE */
|
||||||
{ "boxVr", 0x255F }, /* BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE */
|
{ "boxVr", 0x255F }, /* BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE */
|
||||||
{ "boxdL", 0x2555 }, /* BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE */
|
{ "boxdL", 0x2555 }, /* BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE */
|
||||||
@ -339,7 +339,7 @@ struct entity { char *s; unicode_val_T c; } entities [1002] = {
|
|||||||
{ "boxul", 0x2518 }, /* BOX DRAWINGS LIGHT UP AND LEFT */
|
{ "boxul", 0x2518 }, /* BOX DRAWINGS LIGHT UP AND LEFT */
|
||||||
{ "boxur", 0x2514 }, /* BOX DRAWINGS LIGHT UP AND RIGHT */
|
{ "boxur", 0x2514 }, /* BOX DRAWINGS LIGHT UP AND RIGHT */
|
||||||
{ "boxv", 0x2502 }, /* BOX DRAWINGS LIGHT VERTICAL */
|
{ "boxv", 0x2502 }, /* BOX DRAWINGS LIGHT VERTICAL */
|
||||||
{"boxvH", 0x256A}, /* BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DO*/
|
{ "boxvH", 0x256A }, /* BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE */
|
||||||
{ "boxvL", 0x2561 }, /* BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE */
|
{ "boxvL", 0x2561 }, /* BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE */
|
||||||
{ "boxvR", 0x255E }, /* BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE */
|
{ "boxvR", 0x255E }, /* BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE */
|
||||||
{ "boxvh", 0x253C }, /* BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */
|
{ "boxvh", 0x253C }, /* BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */
|
||||||
@ -539,7 +539,7 @@ struct entity { char *s; unicode_val_T c; } entities [1002] = {
|
|||||||
{ "iacute", 0x00ED }, /* LATIN SMALL LETTER I WITH ACUTE */
|
{ "iacute", 0x00ED }, /* LATIN SMALL LETTER I WITH ACUTE */
|
||||||
{ "icirc", 0x00EE }, /* LATIN SMALL LETTER I WITH CIRCUMFLEX */
|
{ "icirc", 0x00EE }, /* LATIN SMALL LETTER I WITH CIRCUMFLEX */
|
||||||
{ "icy", 0x0438 }, /* CYRILLIC SMALL LETTER I */
|
{ "icy", 0x0438 }, /* CYRILLIC SMALL LETTER I */
|
||||||
{"idiagr", 0x0390}, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TON*/
|
{ "idiagr", 0x0390 }, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */
|
||||||
{ "idigr", 0x03CA }, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA */
|
{ "idigr", 0x03CA }, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA */
|
||||||
{ "iecy", 0x0435 }, /* CYRILLIC SMALL LETTER IE */
|
{ "iecy", 0x0435 }, /* CYRILLIC SMALL LETTER IE */
|
||||||
{ "iexcl", 0x00A1 }, /* INVERTED EXCLAMATION MARK */
|
{ "iexcl", 0x00A1 }, /* INVERTED EXCLAMATION MARK */
|
||||||
|
@ -267,7 +267,7 @@ get_address(struct socket_info *info, enum addr_type type)
|
|||||||
info->addr = (struct sockaddr *) sin;
|
info->addr = (struct sockaddr *) sin;
|
||||||
info->size = sizeof(*sin);
|
info->size = sizeof(*sin);
|
||||||
|
|
||||||
return AF_INET;
|
return PF_INET;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -373,12 +373,12 @@ bind_to_af_unix(void)
|
|||||||
{
|
{
|
||||||
mode_t saved_mask = umask(0177);
|
mode_t saved_mask = umask(0177);
|
||||||
int attempts = 0;
|
int attempts = 0;
|
||||||
int af = get_address(&s_info_listen, ADDR_IP_SERVER);
|
int pf = get_address(&s_info_listen, ADDR_IP_SERVER);
|
||||||
|
|
||||||
if (af == -1) goto free_and_error;
|
if (pf == -1) goto free_and_error;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
s_info_listen.fd = socket(af, SOCK_STREAM, 0);
|
s_info_listen.fd = socket(pf, SOCK_STREAM, 0);
|
||||||
if (s_info_listen.fd == -1) {
|
if (s_info_listen.fd == -1) {
|
||||||
report_af_unix_error("socket()", errno);
|
report_af_unix_error("socket()", errno);
|
||||||
goto free_and_error;
|
goto free_and_error;
|
||||||
@ -435,12 +435,12 @@ static int
|
|||||||
connect_to_af_unix(void)
|
connect_to_af_unix(void)
|
||||||
{
|
{
|
||||||
int attempts = 0;
|
int attempts = 0;
|
||||||
int af = get_address(&s_info_connect, ADDR_IP_CLIENT);
|
int pf = get_address(&s_info_connect, ADDR_IP_CLIENT);
|
||||||
|
|
||||||
while (af != -1 && attempts++ < MAX_CONNECT_TRIES) {
|
while (pf != -1 && attempts++ < MAX_CONNECT_TRIES) {
|
||||||
int saved_errno;
|
int saved_errno;
|
||||||
|
|
||||||
s_info_connect.fd = socket(af, SOCK_STREAM, 0);
|
s_info_connect.fd = socket(pf, SOCK_STREAM, 0);
|
||||||
if (s_info_connect.fd == -1) {
|
if (s_info_connect.fd == -1) {
|
||||||
report_af_unix_error("socket()", errno);
|
report_af_unix_error("socket()", errno);
|
||||||
break;
|
break;
|
||||||
|
@ -49,7 +49,7 @@ struct keepalive_connection {
|
|||||||
timeval_T timeout;
|
timeval_T timeout;
|
||||||
timeval_T creation_time;
|
timeval_T creation_time;
|
||||||
|
|
||||||
unsigned int protocol_family:1; /* 0 == PF_INET, 1 == PF_INET6 */
|
unsigned int protocol_family:1; /* see network/socket.h, EL_PF_INET, EL_PF_INET6 */
|
||||||
int socket;
|
int socket;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -279,7 +279,7 @@ get_pasv_socket(struct socket *ctrl_socket, struct sockaddr_storage *addr)
|
|||||||
#ifdef CONFIG_IPV6
|
#ifdef CONFIG_IPV6
|
||||||
struct sockaddr_in6 bind_addr6;
|
struct sockaddr_in6 bind_addr6;
|
||||||
|
|
||||||
if (ctrl_socket->protocol_family == 1) {
|
if (ctrl_socket->protocol_family == EL_PF_INET6) {
|
||||||
bind_addr = (struct sockaddr *) &bind_addr6;
|
bind_addr = (struct sockaddr *) &bind_addr6;
|
||||||
addrlen = sizeof(bind_addr6);
|
addrlen = sizeof(bind_addr6);
|
||||||
} else
|
} else
|
||||||
@ -303,7 +303,7 @@ sock_error:
|
|||||||
|
|
||||||
/* Get a passive socket */
|
/* Get a passive socket */
|
||||||
|
|
||||||
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
if (sock < 0)
|
if (sock < 0)
|
||||||
goto sock_error;
|
goto sock_error;
|
||||||
|
|
||||||
@ -316,7 +316,7 @@ sock_error:
|
|||||||
|
|
||||||
memcpy(bind_addr, pasv_addr, addrlen);
|
memcpy(bind_addr, pasv_addr, addrlen);
|
||||||
#ifdef CONFIG_IPV6
|
#ifdef CONFIG_IPV6
|
||||||
if (ctrl_socket->protocol_family == 1)
|
if (ctrl_socket->protocol_family == EL_PF_INET6)
|
||||||
bind_addr6.sin6_port = 0;
|
bind_addr6.sin6_port = 0;
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@ -484,6 +484,10 @@ connect_socket(struct socket *csocket, enum connection_state state)
|
|||||||
int only_local = get_cmd_opt_bool("localhost");
|
int only_local = get_cmd_opt_bool("localhost");
|
||||||
int saved_errno = 0;
|
int saved_errno = 0;
|
||||||
int at_least_one_remote_ip = 0;
|
int at_least_one_remote_ip = 0;
|
||||||
|
#ifdef CONFIG_IPV6
|
||||||
|
int try_ipv6 = get_opt_bool("connection.try_ipv6");
|
||||||
|
#endif
|
||||||
|
int try_ipv4 = get_opt_bool("connection.try_ipv4");
|
||||||
/* We tried something but we failed in such a way that we would rather
|
/* We tried something but we failed in such a way that we would rather
|
||||||
* prefer the connection to retain the information about previous
|
* prefer the connection to retain the information about previous
|
||||||
* failures. That is, we i.e. decided we are forbidden to even think
|
* failures. That is, we i.e. decided we are forbidden to even think
|
||||||
@ -501,24 +505,20 @@ connect_socket(struct socket *csocket, enum connection_state state)
|
|||||||
for (i = connect_info->triedno + 1; i < connect_info->addrno; i++) {
|
for (i = connect_info->triedno + 1; i < connect_info->addrno; i++) {
|
||||||
#ifdef CONFIG_IPV6
|
#ifdef CONFIG_IPV6
|
||||||
struct sockaddr_in6 addr = *((struct sockaddr_in6 *) &connect_info->addr[i]);
|
struct sockaddr_in6 addr = *((struct sockaddr_in6 *) &connect_info->addr[i]);
|
||||||
|
int family = addr.sin6_family;
|
||||||
#else
|
#else
|
||||||
struct sockaddr_in addr = *((struct sockaddr_in *) &connect_info->addr[i]);
|
struct sockaddr_in addr = *((struct sockaddr_in *) &connect_info->addr[i]);
|
||||||
|
int family = addr.sin_family;
|
||||||
#endif
|
#endif
|
||||||
int family;
|
int pf;
|
||||||
int force_family = connect_info->ip_family;
|
int force_family = connect_info->ip_family;
|
||||||
|
|
||||||
#ifdef CONFIG_IPV6
|
|
||||||
family = addr.sin6_family;
|
|
||||||
#else
|
|
||||||
family = addr.sin_family;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
connect_info->triedno++;
|
connect_info->triedno++;
|
||||||
|
|
||||||
if (only_local) {
|
if (only_local) {
|
||||||
int local = 0;
|
int local = 0;
|
||||||
#ifdef CONFIG_IPV6
|
#ifdef CONFIG_IPV6
|
||||||
if (addr.sin6_family == AF_INET6)
|
if (family == AF_INET6)
|
||||||
local = check_if_local_address6((struct sockaddr_in6 *) &addr);
|
local = check_if_local_address6((struct sockaddr_in6 *) &addr);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@ -532,18 +532,28 @@ connect_socket(struct socket *csocket, enum connection_state state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_IPV6
|
#ifdef CONFIG_IPV6
|
||||||
if (family == AF_INET6 && (!get_opt_bool("connection.try_ipv6") || (force_family && force_family != 6))) {
|
if (family == AF_INET6) {
|
||||||
|
if (!try_ipv6 || (force_family && force_family != 6)) {
|
||||||
silent_fail = 1;
|
silent_fail = 1;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
pf = PF_INET6;
|
||||||
|
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
if (family == AF_INET && (!get_opt_bool("connection.try_ipv4") || (force_family && force_family != 4))) {
|
if (family == AF_INET) {
|
||||||
|
if (!try_ipv4 || (force_family && force_family != 4)) {
|
||||||
silent_fail = 1;
|
silent_fail = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
pf = PF_INET;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
silent_fail = 0;
|
silent_fail = 0;
|
||||||
|
|
||||||
sock = socket(family, SOCK_STREAM, IPPROTO_TCP);
|
sock = socket(pf, SOCK_STREAM, IPPROTO_TCP);
|
||||||
if (sock == -1) {
|
if (sock == -1) {
|
||||||
if (errno && !saved_errno) saved_errno = errno;
|
if (errno && !saved_errno) saved_errno = errno;
|
||||||
continue;
|
continue;
|
||||||
@ -568,11 +578,11 @@ connect_socket(struct socket *csocket, enum connection_state state)
|
|||||||
* something else ;-). --pasky */
|
* something else ;-). --pasky */
|
||||||
|
|
||||||
#ifdef CONFIG_IPV6
|
#ifdef CONFIG_IPV6
|
||||||
if (addr.sin6_family == AF_INET6) {
|
if (family == AF_INET6) {
|
||||||
if (connect(sock, (struct sockaddr *) &addr,
|
if (connect(sock, (struct sockaddr *) &addr,
|
||||||
sizeof(struct sockaddr_in6)) == 0) {
|
sizeof(struct sockaddr_in6)) == 0) {
|
||||||
/* Success */
|
/* Success */
|
||||||
csocket->protocol_family = 1;
|
csocket->protocol_family = EL_PF_INET6;
|
||||||
complete_connect_socket(csocket, NULL, NULL);
|
complete_connect_socket(csocket, NULL, NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -582,7 +592,7 @@ connect_socket(struct socket *csocket, enum connection_state state)
|
|||||||
if (connect(sock, (struct sockaddr *) &addr,
|
if (connect(sock, (struct sockaddr *) &addr,
|
||||||
sizeof(struct sockaddr_in)) == 0) {
|
sizeof(struct sockaddr_in)) == 0) {
|
||||||
/* Success */
|
/* Success */
|
||||||
csocket->protocol_family = 0;
|
csocket->protocol_family = EL_PF_INET;
|
||||||
complete_connect_socket(csocket, NULL, NULL);
|
complete_connect_socket(csocket, NULL, NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -94,12 +94,14 @@ struct socket {
|
|||||||
* lot of compilation time. --pasky */
|
* lot of compilation time. --pasky */
|
||||||
void *ssl;
|
void *ssl;
|
||||||
|
|
||||||
unsigned int protocol_family:1; /* 0 == PF_INET, 1 == PF_INET6 */
|
unsigned int protocol_family:1; /* EL_PF_INET, EL_PF_INET6 */
|
||||||
unsigned int need_ssl:1; /* If the socket needs SSL support */
|
unsigned int need_ssl:1; /* If the socket needs SSL support */
|
||||||
unsigned int no_tls:1; /* Internal SSL flag. */
|
unsigned int no_tls:1; /* Internal SSL flag. */
|
||||||
unsigned int duplex:1; /* Allow simultaneous reads & writes. */
|
unsigned int duplex:1; /* Allow simultaneous reads & writes. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define EL_PF_INET 0
|
||||||
|
#define EL_PF_INET6 1
|
||||||
|
|
||||||
/* Socket management: */
|
/* Socket management: */
|
||||||
|
|
||||||
|
@ -51,9 +51,9 @@ be_close(int s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
be_socket(int af, int sock, int prot)
|
be_socket(int pf, int sock, int prot)
|
||||||
{
|
{
|
||||||
int h = socket(af, sock, prot);
|
int h = socket(pf, sock, prot);
|
||||||
|
|
||||||
if (h < 0) return h;
|
if (h < 0) return h;
|
||||||
return h + SHS;
|
return h + SHS;
|
||||||
@ -122,13 +122,13 @@ be_pipe(int *fd)
|
|||||||
int retry_count = 0;
|
int retry_count = 0;
|
||||||
|
|
||||||
again:
|
again:
|
||||||
s1 = be_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
s1 = be_socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
if (s1 < 0) {
|
if (s1 < 0) {
|
||||||
/*perror("socket1");*/
|
/*perror("socket1");*/
|
||||||
goto fatal_retry;
|
goto fatal_retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
s2 = be_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
s2 = be_socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
if (s2 < 0) {
|
if (s2 < 0) {
|
||||||
/*perror("socket2");*/
|
/*perror("socket2");*/
|
||||||
be_close(s1);
|
be_close(s1);
|
||||||
|
@ -82,13 +82,13 @@
|
|||||||
#include "osdep/getifaddrs.h"
|
#include "osdep/getifaddrs.h"
|
||||||
|
|
||||||
|
|
||||||
#if (defined(AF_INET6) && defined(SIOCGIF6CONF) && defined(SIOCGIF6FLAGS)) \
|
#if (defined(PF_INET6) && defined(SIOCGIF6CONF) && defined(SIOCGIF6FLAGS)) \
|
||||||
|| (defined(AF_INET) && defined(SIOCGIFCONF) && defined(SIOCGIFFLAGS)) \
|
|| (defined(PF_INET) && defined(SIOCGIFCONF) && defined(SIOCGIFFLAGS)) \
|
||||||
|| (defined(CONFIG_IPV6) && defined(SIOCGIFCONF))
|
|| (defined(CONFIG_IPV6) && defined(SIOCGIFCONF))
|
||||||
|
|
||||||
static int
|
static int
|
||||||
getifaddrs2(struct ifaddrs **ifap,
|
getifaddrs2(struct ifaddrs **ifap,
|
||||||
int af, int siocgifconf, int siocgifflags, size_t ifreq_sz)
|
int pf, int siocgifconf, int siocgifflags, size_t ifreq_sz)
|
||||||
{
|
{
|
||||||
struct sockaddr sa_zero;
|
struct sockaddr sa_zero;
|
||||||
struct ifreq *ifr;
|
struct ifreq *ifr;
|
||||||
@ -104,7 +104,7 @@ getifaddrs2(struct ifaddrs **ifap,
|
|||||||
int num, j = 0;
|
int num, j = 0;
|
||||||
|
|
||||||
memset(&sa_zero, 0, sizeof(sa_zero));
|
memset(&sa_zero, 0, sizeof(sa_zero));
|
||||||
fd = socket(af, SOCK_DGRAM, 0);
|
fd = socket(pf, SOCK_DGRAM, 0);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -240,19 +240,19 @@ getifaddrs(struct ifaddrs **ifap)
|
|||||||
|
|
||||||
errno = ENXIO;
|
errno = ENXIO;
|
||||||
|
|
||||||
#if defined(AF_INET6) && defined(SIOCGIF6CONF) && defined(SIOCGIF6FLAGS)
|
#if defined(PF_INET6) && defined(SIOCGIF6CONF) && defined(SIOCGIF6FLAGS)
|
||||||
if (ret)
|
if (ret)
|
||||||
ret = getifaddrs2(ifap, AF_INET6, SIOCGIF6CONF, SIOCGIF6FLAGS,
|
ret = getifaddrs2(ifap, PF_INET6, SIOCGIF6CONF, SIOCGIF6FLAGS,
|
||||||
sizeof(struct in6_ifreq));
|
sizeof(struct in6_ifreq));
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_IPV6) && defined(SIOCGIFCONF)
|
#if defined(CONFIG_IPV6) && defined(SIOCGIFCONF)
|
||||||
if (ret)
|
if (ret)
|
||||||
ret = getifaddrs2(ifap, AF_INET6, SIOCGIFCONF, SIOCGIFFLAGS,
|
ret = getifaddrs2(ifap, PF_INET6, SIOCGIFCONF, SIOCGIFFLAGS,
|
||||||
sizeof(struct ifreq));
|
sizeof(struct ifreq));
|
||||||
#endif
|
#endif
|
||||||
#if defined(AF_INET) && defined(SIOCGIFCONF) && defined(SIOCGIFFLAGS)
|
#if defined(PF_INET) && defined(SIOCGIFCONF) && defined(SIOCGIFFLAGS)
|
||||||
if (ret)
|
if (ret)
|
||||||
ret = getifaddrs2(ifap, AF_INET, SIOCGIFCONF, SIOCGIFFLAGS,
|
ret = getifaddrs2(ifap, PF_INET, SIOCGIFCONF, SIOCGIFFLAGS,
|
||||||
sizeof(struct ifreq));
|
sizeof(struct ifreq));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -322,7 +322,7 @@ main()
|
|||||||
{
|
{
|
||||||
struct ifaddrs *a = NULL, *b;
|
struct ifaddrs *a = NULL, *b;
|
||||||
|
|
||||||
getifaddrs2(&a, AF_INET, SIOCGIFCONF, SIOCGIFFLAGS,
|
getifaddrs2(&a, PF_INET, SIOCGIFCONF, SIOCGIFFLAGS,
|
||||||
sizeof(struct ifreq));
|
sizeof(struct ifreq));
|
||||||
print_ifaddrs(a);
|
print_ifaddrs(a);
|
||||||
printf("---\n");
|
printf("---\n");
|
||||||
|
@ -347,9 +347,9 @@ win32_ioctl(int fd, long option, int *flag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
win32_socket(int family, int type, int protocol)
|
win32_socket(int pf, int type, int protocol)
|
||||||
{
|
{
|
||||||
SOCKET s = socket(family, type, protocol);
|
SOCKET s = socket(pf, type, protocol);
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (s == INVALID_SOCKET) {
|
if (s == INVALID_SOCKET) {
|
||||||
@ -359,7 +359,7 @@ win32_socket(int family, int type, int protocol)
|
|||||||
rc = s + SOCK_SHIFT;
|
rc = s + SOCK_SHIFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("family %d, type %d, proto %d -> rc %d", family, type, protocol, rc);
|
TRACE("family %d, type %d, proto %d -> rc %d", pf, type, protocol, rc);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
int win32_write(int fd, const void *buf, unsigned len);
|
int win32_write(int fd, const void *buf, unsigned len);
|
||||||
int win32_read(int fd, void *buf, unsigned len);
|
int win32_read(int fd, void *buf, unsigned len);
|
||||||
int win32_pipe(int *fds);
|
int win32_pipe(int *fds);
|
||||||
int win32_socket(int af, int type, int proto);
|
int win32_socket(int pf, int type, int proto);
|
||||||
int win32_connect(int fd, struct sockaddr *addr, int addr_len);
|
int win32_connect(int fd, struct sockaddr *addr, int addr_len);
|
||||||
int win32_getpeername(int fd, struct sockaddr *addr, int *addr_len);
|
int win32_getpeername(int fd, struct sockaddr *addr, int *addr_len);
|
||||||
int win32_getsockname(int fd, struct sockaddr *addr, int *addr_len);
|
int win32_getsockname(int fd, struct sockaddr *addr, int *addr_len);
|
||||||
@ -33,7 +33,7 @@ char *win32_strerror(int err);
|
|||||||
#define write win32_write
|
#define write win32_write
|
||||||
#define close win32_close
|
#define close win32_close
|
||||||
#define pipe win32_pipe
|
#define pipe win32_pipe
|
||||||
#define socket(af, type, prot) win32_socket(af, type, prot)
|
#define socket(pf, type, prot) win32_socket(pf, type, prot)
|
||||||
#define connect(fd, a, al) win32_connect(fd, a, al)
|
#define connect(fd, a, al) win32_connect(fd, a, al)
|
||||||
#define getpeername(fd, a, al) win32_getpeername(fd, a, al)
|
#define getpeername(fd, a, al) win32_getpeername(fd, a, al)
|
||||||
#define getsockname(fd, a, al) win32_getsockname(fd, a, al)
|
#define getsockname(fd, a, al) win32_getsockname(fd, a, al)
|
||||||
|
@ -369,7 +369,7 @@ init_bittorrent_listening_socket(struct connection *conn)
|
|||||||
if (bittorrent_socket != -1)
|
if (bittorrent_socket != -1)
|
||||||
close(bittorrent_socket);
|
close(bittorrent_socket);
|
||||||
|
|
||||||
bittorrent_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
bittorrent_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
if (bittorrent_socket < 0)
|
if (bittorrent_socket < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
|
@ -585,28 +585,9 @@ remove_bittorrent_peer_from_piece_cache(struct bittorrent_peer_connection *peer)
|
|||||||
static enum bittorrent_state
|
static enum bittorrent_state
|
||||||
create_bittorrent_path(unsigned char *path)
|
create_bittorrent_path(unsigned char *path)
|
||||||
{
|
{
|
||||||
int pos;
|
int ret = mkalldirs(path);
|
||||||
|
|
||||||
if (!*path) return BITTORRENT_STATE_ERROR;
|
return (ret ? BITTORRENT_STATE_ERROR : BITTORRENT_STATE_OK);
|
||||||
|
|
||||||
for (pos = 1; path[pos]; pos++) {
|
|
||||||
unsigned char separator = path[pos];
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (!dir_sep(separator))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
path[pos] = 0;
|
|
||||||
|
|
||||||
ret = mkdir(path, S_IREAD | S_IWRITE | S_IEXEC);
|
|
||||||
|
|
||||||
path[pos] = separator;
|
|
||||||
|
|
||||||
if (ret < 0 && errno != EEXIST)
|
|
||||||
return BITTORRENT_STATE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return BITTORRENT_STATE_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Complementary to the above rmdir()s each directory in the path. */
|
/* Complementary to the above rmdir()s each directory in the path. */
|
||||||
|
@ -3,4 +3,19 @@ include $(top_builddir)/Makefile.config
|
|||||||
|
|
||||||
OBJS = ftp.o parse.o
|
OBJS = ftp.o parse.o
|
||||||
|
|
||||||
|
TEST_PROGS = ftp-parser
|
||||||
|
|
||||||
|
TESTDEPS = \
|
||||||
|
$(top_builddir)/src/osdep/stub.o \
|
||||||
|
$(top_builddir)/src/protocol/date.o \
|
||||||
|
$(top_builddir)/src/protocol/ftp/parse.o \
|
||||||
|
$(top_builddir)/src/util/conv.o \
|
||||||
|
$(top_builddir)/src/util/error.o \
|
||||||
|
$(top_builddir)/src/util/hash.o \
|
||||||
|
$(top_builddir)/src/util/memory.o \
|
||||||
|
$(top_builddir)/src/util/string.o \
|
||||||
|
$(top_builddir)/src/util/time.o
|
||||||
|
|
||||||
|
TESTDEPS-$(CONFIG_DEBUG) += $(top_builddir)/src/util/memdebug.o
|
||||||
|
|
||||||
include $(top_srcdir)/Makefile.lib
|
include $(top_srcdir)/Makefile.lib
|
||||||
|
72
src/protocol/ftp/ftp-parser.c
Normal file
72
src/protocol/ftp/ftp-parser.c
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/* Tool for testing the FTP parser */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "elinks.h"
|
||||||
|
|
||||||
|
#include "protocol/ftp/parse.h"
|
||||||
|
|
||||||
|
|
||||||
|
void die(const char *msg, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
if (msg) {
|
||||||
|
va_start(args, msg);
|
||||||
|
vfprintf(stderr, msg, args);
|
||||||
|
fputs("\n", stderr);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(!!NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct ftp_file_info ftp_info = INIT_FTP_FILE_INFO;
|
||||||
|
unsigned char *response = "";
|
||||||
|
int responselen = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i++) {
|
||||||
|
char *arg = argv[i];
|
||||||
|
|
||||||
|
if (strncmp(arg, "--", 2))
|
||||||
|
break;
|
||||||
|
|
||||||
|
arg += 2;
|
||||||
|
|
||||||
|
if (!strncmp(arg, "response", 8)) {
|
||||||
|
arg += 8;
|
||||||
|
if (*arg == '=') {
|
||||||
|
arg++;
|
||||||
|
response = arg;
|
||||||
|
} else {
|
||||||
|
i++;
|
||||||
|
if (i >= argc)
|
||||||
|
die("--response expects a string");
|
||||||
|
response = argv[i];
|
||||||
|
}
|
||||||
|
responselen = strlen(response);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
die("Unknown argument '%s'", arg - 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!responselen)
|
||||||
|
die("Usage: %s --response \"string\"", argv[0]);
|
||||||
|
|
||||||
|
if (parse_ftp_file_info(&ftp_info, response, responselen))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
@ -592,7 +592,7 @@ get_ftp_data_socket(struct connection *conn, struct string *command)
|
|||||||
#ifdef CONFIG_IPV6
|
#ifdef CONFIG_IPV6
|
||||||
ftp->use_epsv = get_opt_bool("protocol.ftp.use_epsv");
|
ftp->use_epsv = get_opt_bool("protocol.ftp.use_epsv");
|
||||||
|
|
||||||
if (conn->socket->protocol_family == 1) {
|
if (conn->socket->protocol_family == EL_PF_INET6) {
|
||||||
if (ftp->use_epsv) {
|
if (ftp->use_epsv) {
|
||||||
add_to_string(command, "EPSV");
|
add_to_string(command, "EPSV");
|
||||||
|
|
||||||
@ -836,10 +836,10 @@ next:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ftp_data_connect(struct connection *conn, int family, struct sockaddr_storage *sa,
|
ftp_data_connect(struct connection *conn, int pf, struct sockaddr_storage *sa,
|
||||||
int size_of_sockaddr)
|
int size_of_sockaddr)
|
||||||
{
|
{
|
||||||
int fd = socket(family, SOCK_STREAM, 0);
|
int fd = socket(pf, SOCK_STREAM, 0);
|
||||||
|
|
||||||
if (fd < 0 || set_nonblocking_fd(fd) < 0) {
|
if (fd < 0 || set_nonblocking_fd(fd) < 0) {
|
||||||
abort_connection(conn, S_FTP_ERROR);
|
abort_connection(conn, S_FTP_ERROR);
|
||||||
@ -1140,24 +1140,6 @@ ftp_process_dirlist(struct cache_entry *cached, off_t *pos,
|
|||||||
int *tries, int colorize_dir, unsigned char *dircolor)
|
int *tries, int colorize_dir, unsigned char *dircolor)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
#ifdef DEBUG_FTP_PARSER
|
|
||||||
static int debug_ftp_parser = 1;
|
|
||||||
int buflen_orig = buflen;
|
|
||||||
unsigned char *response_orig = NULL;
|
|
||||||
|
|
||||||
if (debug_ftp_parser) {
|
|
||||||
buffer = get_ftp_debug_parse_responses(buffer, buflen);
|
|
||||||
buflen = strlen(buffer);
|
|
||||||
response_orig = buffer;
|
|
||||||
debug_ftp_parser = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define end_ftp_dirlist_processing() do { mem_free_if(response_orig); } while (0)
|
|
||||||
#define get_ftp_dirlist_offset(retval) int_min(retval, buflen_orig)
|
|
||||||
#else
|
|
||||||
#define end_ftp_dirlist_processing() /* Nothing to free */
|
|
||||||
#define get_ftp_dirlist_offset(retval) (retval)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
struct ftp_file_info ftp_info = INIT_FTP_FILE_INFO;
|
struct ftp_file_info ftp_info = INIT_FTP_FILE_INFO;
|
||||||
@ -1180,8 +1162,7 @@ ftp_process_dirlist(struct cache_entry *cached, off_t *pos,
|
|||||||
if (bufp && buf[bufp - 1] == ASCII_CR) bufp--;
|
if (bufp && buf[bufp - 1] == ASCII_CR) bufp--;
|
||||||
} else {
|
} else {
|
||||||
if (!bufp || (!last && bufl < FTP_BUF_SIZE)) {
|
if (!bufp || (!last && bufl < FTP_BUF_SIZE)) {
|
||||||
end_ftp_dirlist_processing();
|
return ret;
|
||||||
return get_ftp_dirlist_offset(ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret += bufp;
|
ret += bufp;
|
||||||
@ -1200,8 +1181,7 @@ ftp_process_dirlist(struct cache_entry *cached, off_t *pos,
|
|||||||
retv = display_dir_entry(cached, pos, tries, colorize_dir,
|
retv = display_dir_entry(cached, pos, tries, colorize_dir,
|
||||||
dircolor, &ftp_info);
|
dircolor, &ftp_info);
|
||||||
if (retv < 0) {
|
if (retv < 0) {
|
||||||
end_ftp_dirlist_processing();
|
return ret;
|
||||||
return get_ftp_dirlist_offset(ret);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_FTP_PARSER
|
#ifdef DEBUG_FTP_PARSER
|
||||||
@ -1221,9 +1201,9 @@ ftp_data_accept(struct connection *conn)
|
|||||||
set_connection_timeout(conn);
|
set_connection_timeout(conn);
|
||||||
clear_handlers(conn->data_socket->fd);
|
clear_handlers(conn->data_socket->fd);
|
||||||
|
|
||||||
if ((conn->socket->protocol_family != 1 && ftp->use_pasv)
|
if ((conn->socket->protocol_family != EL_PF_INET6 && ftp->use_pasv)
|
||||||
#ifdef CONFIG_IPV6
|
#ifdef CONFIG_IPV6
|
||||||
|| (conn->socket->protocol_family == 1 && ftp->use_epsv)
|
|| (conn->socket->protocol_family == EL_PF_INET6 && ftp->use_epsv)
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
newsock = conn->data_socket->fd;
|
newsock = conn->data_socket->fd;
|
||||||
|
@ -32,6 +32,9 @@
|
|||||||
#include "util/time.h"
|
#include "util/time.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Examples of what the FTP parser is supposed to handle (and not handle) can
|
||||||
|
* be found in the test-ftp-parser file. */
|
||||||
|
|
||||||
#define skip_space_end(src, end) \
|
#define skip_space_end(src, end) \
|
||||||
do { while ((src) < (end) && *(src) == ' ') (src)++; } while (0)
|
do { while ((src) < (end) && *(src) == ' ') (src)++; } while (0)
|
||||||
|
|
||||||
@ -59,16 +62,7 @@ parse_ftp_number(unsigned char **src, unsigned char *end, long from, long to)
|
|||||||
/* Parser for the EPLF format (see http://pobox.com/~djb/proto/eplf.txt).
|
/* Parser for the EPLF format (see http://pobox.com/~djb/proto/eplf.txt).
|
||||||
*
|
*
|
||||||
* Lines end with \r\n (CR-LF), but that is handled elsewhere.
|
* Lines end with \r\n (CR-LF), but that is handled elsewhere.
|
||||||
*
|
|
||||||
* Some example EPLF response, with the filename separator (tab) displayed as a
|
|
||||||
* space:
|
|
||||||
*/
|
*/
|
||||||
#ifdef DEBUG_FTP_PARSER
|
|
||||||
static unsigned char ftp_eplf_responses[] =
|
|
||||||
"+i8388621.48594,m825718503,r,s280,\tdjb.html\r\n"
|
|
||||||
"+i8388621.50690,m824255907,/,\t514\r\n"
|
|
||||||
"+i8388621.48598,m824253270,r,s612,\t514.html\r\n";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum ftp_eplf {
|
enum ftp_eplf {
|
||||||
FTP_EPLF_FILENAME = ASCII_TAB, /* Filename follows */
|
FTP_EPLF_FILENAME = ASCII_TAB, /* Filename follows */
|
||||||
@ -128,27 +122,6 @@ parse_ftp_eplf_response(struct ftp_file_info *info, unsigned char *src, int len)
|
|||||||
|
|
||||||
|
|
||||||
/* Parser for UNIX-style listing: */
|
/* Parser for UNIX-style listing: */
|
||||||
#ifdef DEBUG_FTP_PARSER
|
|
||||||
static unsigned char ftp_unix_responses[] =
|
|
||||||
/* ftp.freebsd.org response */
|
|
||||||
"drwxrwxr-x 3 0 0 512 Apr 17 2003 pub\r\n"
|
|
||||||
/* UNIX-style listing, without inum and without blocks: */
|
|
||||||
"-rw-r--r-- 1 root other 531 Jan 29 03:26 README\r\n"
|
|
||||||
"dr-xr-xr-x 2 root other 512 Apr 8 1994 etc\r\n"
|
|
||||||
"dr-xr-xr-x 2 root 512 Apr 8 1994 etc\r\n"
|
|
||||||
"lrwxrwxrwx 1 root other 7 Jan 25 00:17 bin -> usr/bin\r\n"
|
|
||||||
/* Also produced by Microsoft's FTP servers for Windows: */
|
|
||||||
"---------- 1 owner group 1803128 Jul 10 10:18 ls-lR.Z\r\n"
|
|
||||||
"d--------- 1 owner group 0 May 9 19:45 Softlib\r\n"
|
|
||||||
/* Also WFTPD for MSDOS: */
|
|
||||||
"-rwxrwxrwx 1 noone nogroup 322 Aug 19 1996 message.ftp\r\n"
|
|
||||||
/* Also NetWare: */
|
|
||||||
"d [R----F--] supervisor 512 Jan 16 18:53 login\r\n"
|
|
||||||
"- [R----F--] rhesus 214059 Oct 20 15:27 cx.exe\r\n"
|
|
||||||
/* Also NetPresenz for the Mac: */
|
|
||||||
"-------r-- 326 1391972 1392298 Nov 22 1995 MegaPhone.sit\r\n"
|
|
||||||
"drwxrwxr-x folder 2 May 10 1996 network\r\n";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum ftp_unix {
|
enum ftp_unix {
|
||||||
FTP_UNIX_PERMISSIONS,
|
FTP_UNIX_PERMISSIONS,
|
||||||
@ -429,15 +402,6 @@ parse_ftp_unix_response(struct ftp_file_info *info, unsigned char *src, int len)
|
|||||||
|
|
||||||
|
|
||||||
/* Parser for VMS-style MultiNet (some spaces removed from examples): */
|
/* Parser for VMS-style MultiNet (some spaces removed from examples): */
|
||||||
#ifdef DEBUG_FTP_PARSER
|
|
||||||
static unsigned char ftp_vms_responses[] =
|
|
||||||
"00README.TXT;1 2 30-DEC-1996 17:44 [SYSTEM] (RWED,RWED,RE,RE)\r\n"
|
|
||||||
"CORE.DIR;1 1 8-SEP-1996 16:09 [SYSTEM] (RWE,RWE,RE,RE)\r\n"
|
|
||||||
/* And non-MutliNet VMS: */
|
|
||||||
"CII-MANUAL.TEX;1 213/216 29-JAN-1996 03:33:12 [ANONYMOU,ANONYMOUS] (RWED,RWED,,)\r\n"
|
|
||||||
/* A garbage line which should fail: */
|
|
||||||
"EA95_0PS.GZ;1 No privilege for attempted operation\r\n";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Converts VMS symbolic permissions to number-style ones, e.g. string
|
/* Converts VMS symbolic permissions to number-style ones, e.g. string
|
||||||
* RWED,RWE,RE to 755. "D" (delete) is taken to be equal to "W" (write).
|
* RWED,RWE,RE to 755. "D" (delete) is taken to be equal to "W" (write).
|
||||||
@ -554,12 +518,6 @@ parse_ftp_vms_response(struct ftp_file_info *info, unsigned char *src, int len)
|
|||||||
|
|
||||||
|
|
||||||
/* Parser for the MSDOS-style format: */
|
/* Parser for the MSDOS-style format: */
|
||||||
#ifdef DEBUG_FTP_PARSER
|
|
||||||
static unsigned char ftp_winnt_responses[] =
|
|
||||||
"04-27-00 09:09PM <DIR> licensed\r\n"
|
|
||||||
"07-18-00 10:16AM <DIR> pub\r\n"
|
|
||||||
"04-14-00 03:47PM 589 readme.htm\r\n";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct ftp_file_info *
|
struct ftp_file_info *
|
||||||
parse_ftp_winnt_response(struct ftp_file_info *info, unsigned char *src, int len)
|
parse_ftp_winnt_response(struct ftp_file_info *info, unsigned char *src, int len)
|
||||||
@ -639,26 +597,6 @@ parse_ftp_winnt_response(struct ftp_file_info *info, unsigned char *src, int len
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_FTP_PARSER
|
|
||||||
unsigned char *
|
|
||||||
get_ftp_debug_parse_responses(unsigned char *buffer, int buflen)
|
|
||||||
{
|
|
||||||
struct string response;
|
|
||||||
|
|
||||||
if (!init_string(&response))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
add_to_string(&response, ftp_eplf_responses);
|
|
||||||
add_to_string(&response, ftp_unix_responses);
|
|
||||||
add_to_string(&response, ftp_vms_responses);
|
|
||||||
add_to_string(&response, ftp_winnt_responses);
|
|
||||||
|
|
||||||
add_bytes_to_string(&response, buffer, buflen);
|
|
||||||
|
|
||||||
return response.source;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
struct ftp_file_info *
|
struct ftp_file_info *
|
||||||
parse_ftp_file_info(struct ftp_file_info *info, unsigned char *src, int len)
|
parse_ftp_file_info(struct ftp_file_info *info, unsigned char *src, int len)
|
||||||
|
@ -38,14 +38,4 @@ struct ftp_file_info {
|
|||||||
struct ftp_file_info *
|
struct ftp_file_info *
|
||||||
parse_ftp_file_info(struct ftp_file_info *info, unsigned char *src, int len);
|
parse_ftp_file_info(struct ftp_file_info *info, unsigned char *src, int len);
|
||||||
|
|
||||||
/* Define to feed debug FTP responses into the parser. Then point ELinks to an
|
|
||||||
* FTP server to run the tests. */
|
|
||||||
#if 0
|
|
||||||
#define DEBUG_FTP_PARSER
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEBUG_FTP_PARSER
|
|
||||||
unsigned char *get_ftp_debug_parse_responses(unsigned char *buffer, int buflen);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
123
src/protocol/ftp/test-ftp-parser
Normal file
123
src/protocol/ftp/test-ftp-parser
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Copyright (c) 2005 Jonas Fonseca
|
||||||
|
#
|
||||||
|
|
||||||
|
test_description='Test parsing of FTP responses.
|
||||||
|
|
||||||
|
It tests responses from several different FTP servers.
|
||||||
|
'
|
||||||
|
|
||||||
|
. "$TEST_LIB"
|
||||||
|
|
||||||
|
CRNL="\r\n"
|
||||||
|
|
||||||
|
test_ftp_response_expect_success () {
|
||||||
|
desc="$1"; shift
|
||||||
|
response="$1"; shift
|
||||||
|
|
||||||
|
response="$(echo "$response" | sed -n '2,$p')"
|
||||||
|
|
||||||
|
test_expect_success "$desc" \
|
||||||
|
"ftp-parser --response \"$response\""
|
||||||
|
}
|
||||||
|
|
||||||
|
test_ftp_response_expect_failure () {
|
||||||
|
desc="$1"; shift
|
||||||
|
response="$1"; shift
|
||||||
|
|
||||||
|
response="$(echo "$response" | sed -n '2,$p')"
|
||||||
|
|
||||||
|
test_expect_failure "$desc" \
|
||||||
|
"ftp-parser --response \"$response\""
|
||||||
|
}
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
#
|
||||||
|
# Parser for UNIX-style listing:
|
||||||
|
#
|
||||||
|
|
||||||
|
test_ftp_response_expect_success \
|
||||||
|
'ftp.freebsd.org response' \
|
||||||
|
"
|
||||||
|
drwxrwxr-x 3 0 0 512 Apr 17 2003 pub\r\n"
|
||||||
|
|
||||||
|
test_ftp_response_expect_success \
|
||||||
|
'UNIX-style listing, without inum and without blocks' \
|
||||||
|
"
|
||||||
|
-rw-r--r-- 1 root other 531 Jan 29 03:26 README\r\n
|
||||||
|
dr-xr-xr-x 2 root other 512 Apr 8 1994 etc\r\n
|
||||||
|
dr-xr-xr-x 2 root 512 Apr 8 1994 etc\r\n
|
||||||
|
lrwxrwxrwx 1 root other 7 Jan 25 00:17 bin -> usr/bin\r\n"
|
||||||
|
|
||||||
|
test_ftp_response_expect_success \
|
||||||
|
"Response produced by Microsoft's FTP servers for Windows" \
|
||||||
|
"
|
||||||
|
---------- 1 owner group 1803128 Jul 10 10:18 ls-lR.Z\r\n
|
||||||
|
d--------- 1 owner group 0 May 9 19:45 Softlib\r\n"
|
||||||
|
|
||||||
|
test_ftp_response_expect_success \
|
||||||
|
'Response from WFTPD for MSDOS' \
|
||||||
|
"
|
||||||
|
-rwxrwxrwx 1 noone nogroup 322 Aug 19 1996 message.ftp\r\n"
|
||||||
|
|
||||||
|
test_ftp_response_expect_success \
|
||||||
|
'Response from NetWare' \
|
||||||
|
"
|
||||||
|
d[R----F--] supervisor 512 Jan 16 18:53 login\r\n
|
||||||
|
- [R----F--] rhesus 214059 Oct 20 15:27 cx.exe\r\n"
|
||||||
|
|
||||||
|
test_ftp_response_expect_success \
|
||||||
|
'Response from NetPresenz for the Mac' \
|
||||||
|
"
|
||||||
|
-------r-- 326 1391972 1392298 Nov 22 1995 MegaPhone.sit\r\n
|
||||||
|
drwxrwxr-x folder 2 May 10 1996 network\r\n"
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
#
|
||||||
|
# EPLF response
|
||||||
|
#
|
||||||
|
|
||||||
|
test_ftp_response_expect_success \
|
||||||
|
'EPLF responses' \
|
||||||
|
$'
|
||||||
|
+i8388621.48594,m825718503,r,s280,\tdjb.html\r\n
|
||||||
|
+i8388621.50690,m824255907,/,\t514\r\n
|
||||||
|
+i8388621.48598,m824253270,r,s612,\t514.html\r\n'
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
#
|
||||||
|
# Parser for VMS-style MultiNet (some spaces removed from examples)
|
||||||
|
#
|
||||||
|
|
||||||
|
test_ftp_response_expect_success \
|
||||||
|
'Basic VMS responses' \
|
||||||
|
"
|
||||||
|
00README.TXT;1 2 30-DEC-1996 17:44 [SYSTEM] (RWED,RWED,RE,RE)\r\n
|
||||||
|
CORE.DIR;1 1 8-SEP-1996 16:09 [SYSTEM] (RWE,RWE,RE,RE)\r\n"
|
||||||
|
|
||||||
|
test_ftp_response_expect_success \
|
||||||
|
'Response from non-MutliNet VMS' \
|
||||||
|
"
|
||||||
|
CII-MANUAL.TEX;1 213/216 29-JAN-1996 03:33:12 [ANONYMOU,ANONYMOUS] (RWED,RWED,,)\r\n"
|
||||||
|
|
||||||
|
test_ftp_response_expect_failure \
|
||||||
|
'A garbage line which should fail' \
|
||||||
|
"
|
||||||
|
EA95_0PS.GZ;1 No privilege for attempted operation\r\n"
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
#
|
||||||
|
# Parser for the MSDOS-style format
|
||||||
|
#
|
||||||
|
|
||||||
|
test_ftp_response_expect_success \
|
||||||
|
'Basic MSDOS-style format' \
|
||||||
|
"
|
||||||
|
04-27-00 09:09PM <DIR> licensed\r\n
|
||||||
|
07-18-00 10:16AM <DIR> pub\r\n
|
||||||
|
04-14-00 03:47PM 589 readme.htm\r\n"
|
||||||
|
|
||||||
|
|
||||||
|
test_done
|
@ -14,6 +14,7 @@
|
|||||||
#include "scripting/smjs/elinks_object.h"
|
#include "scripting/smjs/elinks_object.h"
|
||||||
#include "scripting/smjs/global_object.h"
|
#include "scripting/smjs/global_object.h"
|
||||||
#include "scripting/smjs/smjs.h"
|
#include "scripting/smjs/smjs.h"
|
||||||
|
#include "util/file.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
|
|
||||||
|
|
||||||
@ -116,6 +117,7 @@ smjs_load_hooks(void)
|
|||||||
path = stracpy(CONFDIR "/" SMJS_HOOKS_FILENAME);
|
path = stracpy(CONFDIR "/" SMJS_HOOKS_FILENAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (file_exists(path))
|
||||||
smjs_do_file(path);
|
smjs_do_file(path);
|
||||||
mem_free(path);
|
mem_free(path);
|
||||||
}
|
}
|
||||||
|
@ -573,6 +573,9 @@ create_download_file_do(struct terminal *term, unsigned char *file, void *data,
|
|||||||
wd = get_cwd();
|
wd = get_cwd();
|
||||||
set_cwd(term->cwd);
|
set_cwd(term->cwd);
|
||||||
|
|
||||||
|
/* Create parent directories if needed. */
|
||||||
|
mkalldirs(file);
|
||||||
|
|
||||||
/* O_APPEND means repositioning at the end of file before each write(),
|
/* O_APPEND means repositioning at the end of file before each write(),
|
||||||
* thus ignoring seek()s and that can hide mysterious bugs. IMHO.
|
* thus ignoring seek()s and that can hide mysterious bugs. IMHO.
|
||||||
* --pasky */
|
* --pasky */
|
||||||
|
@ -205,7 +205,7 @@ update_screen_driver(struct screen_driver *driver, struct option *term_spec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (utf8_io) {
|
if (utf8_io) {
|
||||||
driver->charsets[0] = get_opt_int_tree(term_spec, "charset");
|
driver->charsets[0] = get_opt_codepage_tree(term_spec, "charset");
|
||||||
if (driver->type == TERM_LINUX) {
|
if (driver->type == TERM_LINUX) {
|
||||||
if (get_opt_bool_tree(term_spec, "restrict_852"))
|
if (get_opt_bool_tree(term_spec, "restrict_852"))
|
||||||
driver->frame = frame_restrict;
|
driver->frame = frame_restrict;
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -46,7 +47,7 @@
|
|||||||
#include "util/file.h"
|
#include "util/file.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
#include "protocol/uri.h"
|
|
||||||
|
|
||||||
/* Not that these two would be so useful for portability (they are ANSI C) but
|
/* Not that these two would be so useful for portability (they are ANSI C) but
|
||||||
* they encapsulate the lowlevel stuff (need for <unistd.h>) nicely. */
|
* they encapsulate the lowlevel stuff (need for <unistd.h>) nicely. */
|
||||||
@ -54,29 +55,12 @@
|
|||||||
int
|
int
|
||||||
file_exists(const unsigned char *filename)
|
file_exists(const unsigned char *filename)
|
||||||
{
|
{
|
||||||
int result;
|
|
||||||
unsigned char *decoded_filename;
|
|
||||||
#ifdef HAVE_ACCESS
|
#ifdef HAVE_ACCESS
|
||||||
|
return access(filename, F_OK) >= 0;
|
||||||
result = access(filename, F_OK);
|
|
||||||
if (result >= 0) return 1;
|
|
||||||
decoded_filename = stracpy((unsigned char *)filename);
|
|
||||||
if (!decoded_filename) return 0;
|
|
||||||
decode_uri(decoded_filename);
|
|
||||||
result = access(decoded_filename, F_OK);
|
|
||||||
mem_free(decoded_filename);
|
|
||||||
return result >= 0;
|
|
||||||
#else
|
#else
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
|
|
||||||
result = stat(filename, &buf);
|
return stat(filename, &buf) >= 0;
|
||||||
if (result >= 0) return 1;
|
|
||||||
decoded_filename = stracpy((unsigned char *)filename);
|
|
||||||
if (!decoded_filename) return 0;
|
|
||||||
decode_uri(decoded_filename);
|
|
||||||
result = stat(decoded_filename, &buf);
|
|
||||||
mem_free(decoded_filename);
|
|
||||||
return result >= 0;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -597,3 +581,40 @@ get_directory_entries(unsigned char *dirname, int get_hidden)
|
|||||||
|
|
||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Recursively create directories in a path. The last element in the path is
|
||||||
|
* taken to be a filename, and simply ignored */
|
||||||
|
int
|
||||||
|
mkalldirs(const unsigned char *path)
|
||||||
|
{
|
||||||
|
int pos, len, ret = 0;
|
||||||
|
unsigned char *p;
|
||||||
|
|
||||||
|
if (!*path) return -1;
|
||||||
|
|
||||||
|
/* Make a copy of path, to be able to write to it. Otherwise, the
|
||||||
|
* function is unsafe if called with a read-only char *argument. */
|
||||||
|
len = strlen(path) + 1;
|
||||||
|
p = fmem_alloc(len);
|
||||||
|
if (!p) return -1;
|
||||||
|
memcpy(p, path, len);
|
||||||
|
|
||||||
|
for (pos = 1; p[pos]; pos++) {
|
||||||
|
unsigned char separator = p[pos];
|
||||||
|
|
||||||
|
if (!dir_sep(separator))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
p[pos] = 0;
|
||||||
|
|
||||||
|
ret = mkdir(p, S_IREAD | S_IWRITE | S_IEXEC);
|
||||||
|
|
||||||
|
p[pos] = separator;
|
||||||
|
|
||||||
|
if (ret < 0 && errno != EEXIST)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fmem_free(p);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@ -51,4 +51,8 @@ unsigned char *file_read_line(unsigned char *line, size_t *linesize,
|
|||||||
* restore previous umask(). */
|
* restore previous umask(). */
|
||||||
int safe_mkstemp(unsigned char *template);
|
int safe_mkstemp(unsigned char *template);
|
||||||
|
|
||||||
|
/* Recursively create directories in a path. The last element in the path is
|
||||||
|
* taken to be a filename, and simply ignored */
|
||||||
|
int mkalldirs(const unsigned char *path);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user