mirror of
https://github.com/rkd77/elinks.git
synced 2024-12-04 14:46:47 -05:00
Merge commit 'pasky.or.cz/elinks-0.12' into elinks-0.13
This commit is contained in:
commit
ab9e0821d6
3
NEWS
3
NEWS
@ -71,6 +71,7 @@ Miscellaneous:
|
|||||||
* gzip_read: always call gzclearerr
|
* gzip_read: always call gzclearerr
|
||||||
* bug 816: convert entity references in input/@value only once
|
* bug 816: convert entity references in input/@value only once
|
||||||
* bug 916: if a mailcap entry has no %s, provide the file as stdin
|
* bug 916: if a mailcap entry has no %s, provide the file as stdin
|
||||||
|
* bug 744: don't change ``//'' to ``/'' in URIs
|
||||||
* bug 766: speed up CSS
|
* bug 766: speed up CSS
|
||||||
* bug 355: add documents displayed via ``What to do'' dialog to the
|
* bug 355: add documents displayed via ``What to do'' dialog to the
|
||||||
global history
|
global history
|
||||||
@ -125,7 +126,7 @@ Build system and compile-time errors (ignore if you don't build ELinks):
|
|||||||
* enhancement: avoid compilation of vernum.c in 'make install'
|
* enhancement: avoid compilation of vernum.c in 'make install'
|
||||||
* enhancement: make uninstall
|
* enhancement: make uninstall
|
||||||
* experimental enhancements: --with-python=DIRECTORY, --with-gc=DIRECTORY
|
* experimental enhancements: --with-python=DIRECTORY, --with-gc=DIRECTORY
|
||||||
* experimental enhancement: native Win32 port
|
* experimental enhancement: Win32 port (build with MinGW MSYS)
|
||||||
|
|
||||||
Changes in the experimental ECMAScript support:
|
Changes in the experimental ECMAScript support:
|
||||||
|
|
||||||
|
@ -21,7 +21,8 @@ echo timestamp > stamp-h.in
|
|||||||
echo autoconf...
|
echo autoconf...
|
||||||
autoconf
|
autoconf
|
||||||
|
|
||||||
echo config.cache...
|
echo config.cache, autom4te.cache...
|
||||||
rm -f config.cache
|
rm -f config.cache
|
||||||
|
rm -rf autom4te.cache
|
||||||
|
|
||||||
echo done
|
echo done
|
||||||
|
@ -14,7 +14,7 @@ AC_DEFUN([EL_CONFIG_OS_WIN32],
|
|||||||
EL_RESTORE_FLAGS
|
EL_RESTORE_FLAGS
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_CHECK_HEADERS(windows.h)
|
AC_CHECK_HEADERS(windows.h ws2tcpip.h)
|
||||||
|
|
||||||
# TODO: Check this?
|
# TODO: Check this?
|
||||||
# TODO: Check -lws2_32 for IPv6 support
|
# TODO: Check -lws2_32 for IPv6 support
|
||||||
|
174
contrib/mkdist
Normal file → Executable file
174
contrib/mkdist
Normal file → Executable file
@ -2,11 +2,21 @@
|
|||||||
#
|
#
|
||||||
# This script can be used by a cron to generate snapshots.
|
# This script can be used by a cron to generate snapshots.
|
||||||
# For example, use:
|
# For example, use:
|
||||||
# 35 0 * * * mkdist elinks-0.11 0.11 >>mkdist.log 2>&1
|
# 35 0 * * * mkdist -r elinks-0.11 -l 0.11 -s >>mkdist.log 2>&1
|
||||||
# 40 0 * * * mkdist HEAD 0.12 >>mkdist.log 2>&1
|
# 40 0 * * * mkdist -r HEAD -l 0.12 -s >>mkdist.log 2>&1
|
||||||
#
|
#
|
||||||
# To generate a release (which doesn't have a date in the
|
# Options:
|
||||||
# top-level directory) also pass -r as the third parameter.
|
# -g GIT_DIR Git repository from which this script exports ELinks.
|
||||||
|
# May be given in the environment instead.
|
||||||
|
# -r REVISION Git revision to be exported from the repository.
|
||||||
|
# -l LABEL User-friendly name of the branch or release.
|
||||||
|
# This ends up in the name of the tar file, and in the
|
||||||
|
# name of the directory it contains.
|
||||||
|
# -s Generate a snapshot (which has a date in the top-level
|
||||||
|
# directory).
|
||||||
|
# -d DOCDIR Copy prebuilt documentation from DOCDIR.
|
||||||
|
# -o OUTDIR Place the output files in OUTDIR. Defaults to the
|
||||||
|
# current directory.
|
||||||
|
|
||||||
# set -x
|
# set -x
|
||||||
|
|
||||||
@ -15,64 +25,118 @@ echo "Date: $(date)"
|
|||||||
echo "Args: $*"
|
echo "Args: $*"
|
||||||
echo "-------------------------------------------------"
|
echo "-------------------------------------------------"
|
||||||
|
|
||||||
ub=$1
|
# Variables used in this script:
|
||||||
lb=$2
|
# $GIT_DIR = option -g GIT_DIR; passed in environment to Git
|
||||||
|
# $OPTARG = Bash special: argument of the option being parsed
|
||||||
|
# $OPTIND = Bash special: index of argument to be parsed next
|
||||||
|
# $commit = commit ID corresponding to $rev
|
||||||
|
# $docdir = option -d DOCDIR
|
||||||
|
# $label = option -l LABEL
|
||||||
|
# $opt = option letter being parsed, or '?' on error
|
||||||
|
# $outdir = option -o OUTDIR
|
||||||
|
# $rev = option -r REVISION
|
||||||
|
# $snap = option -s
|
||||||
|
# $tarbasename = name of the tar file without .tar.* extensions
|
||||||
|
# $tartopdir = name of the top directory within the tar file
|
||||||
|
# $tmpdir = temporary directory created by this script
|
||||||
|
|
||||||
GIT_DIR="elinks-repo-directory"
|
rev=
|
||||||
DOC_DIR="" # Leave empty for no doc dir
|
label=
|
||||||
TMP_DIR="/tmp/elinks-git.$$"
|
snap=
|
||||||
TAR_DIR="elinks-snapshot-directory"
|
docdir=
|
||||||
|
outdir=.
|
||||||
|
while getopts "g:r:l:sd:o:" opt
|
||||||
|
do
|
||||||
|
case "$opt" in
|
||||||
|
(g) GIT_DIR=$OPTARG ;;
|
||||||
|
(r) rev=$OPTARG ;;
|
||||||
|
(l) label=$OPTARG ;;
|
||||||
|
(s) snap=1 ;;
|
||||||
|
(d) docdir=$OPTARG ;;
|
||||||
|
(o) outdir=$OPTARG ;;
|
||||||
|
("?") exit 1 ;;
|
||||||
|
(*) echo >&2 "$0:$LINENO: bug found"
|
||||||
|
exit 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
[ "$ub" ] || exit 1
|
if [ $OPTIND -le $# ]
|
||||||
[ "$lb" ] || exit 1
|
then
|
||||||
|
echo >&2 "$0: too many non-option arguments"
|
||||||
if [ "$3" != "-r" ]; then
|
exit 1
|
||||||
ver=$lb-`date +%Y%m%d`
|
|
||||||
c="-current";
|
|
||||||
else
|
|
||||||
ver=$lb;
|
|
||||||
c="";
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir "$TMP_DIR
|
if [ -z "$GIT_DIR" ]
|
||||||
cd "$TMP_DIR"
|
then
|
||||||
|
echo >&2 "$0: Must specify -g GIT_DIR option"
|
||||||
GIT_DIR="$GIT_DIR" cg-export -r "$ub" "$TMP_DIR"/elinks"
|
exit 1
|
||||||
|
fi
|
||||||
cd elinks
|
if [ -z "$outdir" ]
|
||||||
|
then
|
||||||
./autogen.sh
|
echo >&2 "$0: Must specify -o OUTDIR option"
|
||||||
./configure
|
exit 1
|
||||||
|
fi
|
||||||
if [ "$ub" = "REL_0_10" ]; then
|
if [ -z "$rev" ]
|
||||||
make dist
|
then
|
||||||
tar xfz elinks-$lb*.tar.gz
|
echo >&2 "$0: Must specify -r REVISION option"
|
||||||
cd elinks-$ub*
|
exit 1
|
||||||
else
|
fi
|
||||||
make -C po
|
if [ -z "$label" ]
|
||||||
|
then
|
||||||
|
label=$rev
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test -n "$DOC_DIR"; then
|
commit=$(GIT_DIR=$GIT_DIR cg-object-id -c "$rev") || exit 1
|
||||||
mkdir doc/html
|
|
||||||
cp -r "$DOC_DIR"/*.html* doc/html
|
if [ "$snap" ]
|
||||||
|
then
|
||||||
|
tartopdir=elinks-$label-$(date +%Y%m%d)
|
||||||
|
tarbasename=elinks-current-$label
|
||||||
|
else
|
||||||
|
tartopdir=elinks-$label
|
||||||
|
tarbasename=elinks-$label
|
||||||
|
fi
|
||||||
|
|
||||||
|
tmpdir=$(mktemp -d -t elinks-dist-XXXXXXXX) || exit 1
|
||||||
|
|
||||||
|
# To make it easier to compare build logs, put the source first in an
|
||||||
|
# "elinks" directory, and only move to "$tartopdir" when finished.
|
||||||
|
|
||||||
|
GIT_DIR=$GIT_DIR cg-export -r "$rev" -- "$tmpdir/elinks"
|
||||||
|
mkdir -- "$tmpdir/elinks/.git"
|
||||||
|
printf "%s\n" "$commit" > "$tmpdir/elinks/.git/HEAD"
|
||||||
|
|
||||||
|
(set -e
|
||||||
|
cd -- "$tmpdir/elinks"
|
||||||
|
./autogen.sh
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
../configure
|
||||||
|
make -C po
|
||||||
|
mv po/*.gmo ../po/
|
||||||
|
mv contrib/elinks.spec ../contrib/
|
||||||
|
) || exit 1
|
||||||
|
|
||||||
|
if [ -n "$docdir" ]; then
|
||||||
|
mkdir -- "$tmpdir/elinks/doc/html"
|
||||||
|
cp -r -- "$docdir"/*.html* "$tmpdir/elinks/doc/html/"
|
||||||
# mkdir doc/pdf
|
# mkdir doc/pdf
|
||||||
# cp "$DOC_DIR"/*.pdf doc/pdf
|
# cp "$docdir"/*.pdf doc/pdf
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd ..
|
rm -rf -- "$tmpdir/elinks/build"
|
||||||
|
mv -- "$tmpdir/elinks" "$tmpdir/$tartopdir"
|
||||||
|
|
||||||
if [ "$c" ]; then
|
(set -e
|
||||||
dir=`ls .`
|
cd -- "$tmpdir"
|
||||||
mv $dir elinks-$ver
|
tar cf "$tarbasename.tar" "$tartopdir"
|
||||||
fi
|
md5sum --binary -- "$tarbasename.tar" > "$tarbasename.md5"
|
||||||
|
bzip2 --keep -- "$tarbasename.tar"
|
||||||
|
gzip -9 -- "$tarbasename.tar"
|
||||||
tar cfz elinks$c-$lb.tar.gz elinks-$ver && \
|
md5sum --binary -- "$tarbasename.tar.gz" "$tarbasename.tar.bz2" >> "$tarbasename.md5"
|
||||||
mv elinks$c-$lb.tar.gz "$TAR_DIR" && \
|
) || exit 1
|
||||||
(cd "$TAR_DIR" && md5sum elinks$c-$lb.tar.gz > elinks$c-$lb.tar.gz.md5)
|
|
||||||
|
mv -- "$tmpdir/$tarbasename.tar.gz" "$outdir"
|
||||||
tar cfj elinks$c-$lb.tar.bz2 elinks-$ver && \
|
mv -- "$tmpdir/$tarbasename.tar.bz2" "$outdir"
|
||||||
mv elinks$c-$lb.tar.bz2 "$TAR_DIR" && \
|
mv -- "$tmpdir/$tarbasename.md5" "$outdir"
|
||||||
(cd "$TAR_DIR" && md5sum elinks$c-$lb.tar.bz2 > elinks$c-$lb.tar.gz.md5)
|
rm -rf -- "$tmpdir"
|
||||||
|
|
||||||
rm -rf "$TMP_DIR"
|
|
||||||
|
3
contrib/proxy/.gitignore
vendored
Normal file
3
contrib/proxy/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
gen
|
||||||
|
proxy.py
|
||||||
|
*.http
|
@ -121,10 +121,10 @@ dicts(FILE *f)
|
|||||||
|
|
||||||
fprintf(f, "slownik = {\n");
|
fprintf(f, "slownik = {\n");
|
||||||
for (i = 0; i < counter - 1; i++) {
|
for (i = 0; i < counter - 1; i++) {
|
||||||
fprintf(f, "\t'http://%s%s' : '%d.txt',\n", tab[i].host, tab[i].string, i);
|
fprintf(f, "\t'http://%s%s' : '%d.http',\n", tab[i].host, tab[i].string, i);
|
||||||
}
|
}
|
||||||
for (; i < counter; i++) {
|
for (; i < counter; i++) {
|
||||||
fprintf(f, "\t'http://%s%s' : '%d.txt'\n", tab[i].host, tab[i].string, i);
|
fprintf(f, "\t'http://%s%s' : '%d.http'\n", tab[i].host, tab[i].string, i);
|
||||||
}
|
}
|
||||||
fprintf(f, "}\n\n");
|
fprintf(f, "}\n\n");
|
||||||
}
|
}
|
||||||
@ -138,7 +138,7 @@ save(void)
|
|||||||
for (i = 0; i < counter; i++) {
|
for (i = 0; i < counter; i++) {
|
||||||
char buf[12];
|
char buf[12];
|
||||||
|
|
||||||
snprintf(buf, 12, "%d.txt", i);
|
snprintf(buf, 12, "%d.http", i);
|
||||||
f = fopen(buf, "w");
|
f = fopen(buf, "w");
|
||||||
if (!f)
|
if (!f)
|
||||||
return;
|
return;
|
||||||
|
15
doc/Makefile
15
doc/Makefile
@ -4,7 +4,7 @@ include $(top_builddir)/Makefile.config
|
|||||||
SUBDIRS = man
|
SUBDIRS = man
|
||||||
|
|
||||||
# A little trick to simplify some of the rules.
|
# A little trick to simplify some of the rules.
|
||||||
VPATH = $(builddir):$(srcdir):$(top_srcdir)/contrib/perl:$(top_srcdir)/po/perl
|
VPATH = $(builddir):$(srcdir):$(top_srcdir)/contrib/perl
|
||||||
|
|
||||||
docdir = $(datadir)/doc
|
docdir = $(datadir)/doc
|
||||||
|
|
||||||
@ -43,11 +43,9 @@ HTML_DOCS-$(CONFIG_POD2HTML) += \
|
|||||||
perl.html \
|
perl.html \
|
||||||
perl-hooks.html
|
perl-hooks.html
|
||||||
|
|
||||||
# Don't install these documents, because the corresponding scripts
|
# We don't nowadays run pod2html on the po/perl/ scripts, because
|
||||||
# are not installed either. However, generating them may be useful.
|
# "make install" does not install them and they do not have the .pl
|
||||||
HTML_DOCS_NOINSTALL-$(CONFIG_POD2HTML) += \
|
# suffix expected by the pod2html rule below.
|
||||||
perl-check-accelerator-conflicts.html \
|
|
||||||
perl-gather-accelerator-contexts.html
|
|
||||||
|
|
||||||
MAN_DOCS-$(CONFIG_XMLTO) += \
|
MAN_DOCS-$(CONFIG_XMLTO) += \
|
||||||
elinks.1 \
|
elinks.1 \
|
||||||
@ -64,11 +62,10 @@ PDF_DOCS-$(CONFIG_JW) += \
|
|||||||
|
|
||||||
MAN_DOCS = $(MAN_DOCS-yes)
|
MAN_DOCS = $(MAN_DOCS-yes)
|
||||||
HTML_DOCS = $(HTML_DOCS-yes)
|
HTML_DOCS = $(HTML_DOCS-yes)
|
||||||
HTML_DOCS_NOINSTALL = $(HTML_DOCS_NOINSTALL-yes)
|
|
||||||
PDF_DOCS = $(PDF_DOCS-yes)
|
PDF_DOCS = $(PDF_DOCS-yes)
|
||||||
|
|
||||||
txt: $(TXT_DOCS_NOINSTALL)
|
txt: $(TXT_DOCS_NOINSTALL)
|
||||||
html: txt $(HTML_DOCS) $(HTML_DOCS_NOINSTALL)
|
html: txt $(HTML_DOCS)
|
||||||
pdf: txt $(PDF_DOCS)
|
pdf: txt $(PDF_DOCS)
|
||||||
man: txt $(MAN_DOCS)
|
man: txt $(MAN_DOCS)
|
||||||
|
|
||||||
@ -97,7 +94,7 @@ update-man: man
|
|||||||
$(call ncmd,installdata,elinks.conf.5,$(srcdir)man/man5/))
|
$(call ncmd,installdata,elinks.conf.5,$(srcdir)man/man5/))
|
||||||
|
|
||||||
clean-local:
|
clean-local:
|
||||||
@$(RM) -r api $(TXT_DOCS_NOINSTALL) $(MAN_DOCS) $(HTML_DOCS) $(HTML_DOCS_NOINSTALL) $(PDF_DOCS) *.tmp *.xml
|
@$(RM) -r api $(TXT_DOCS_NOINSTALL) $(MAN_DOCS) $(HTML_DOCS) $(PDF_DOCS) *.tmp *.xml
|
||||||
|
|
||||||
# TODO: perl.pod should be pod2ized during make install. --pasky
|
# TODO: perl.pod should be pod2ized during make install. --pasky
|
||||||
install-local:
|
install-local:
|
||||||
|
@ -53,7 +53,7 @@ $(srcdir)$(POTFILES_ABS_LIST): $(POTFILES_REL)
|
|||||||
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)
|
||||||
|
|
||||||
$(srcdir)$(PACKAGE).pot: $(srcdir)$(POTFILES_ABS_LIST) $(srcdir)perl/gather-accelerator-contexts.pl
|
$(srcdir)$(PACKAGE).pot: $(srcdir)$(POTFILES_ABS_LIST) $(srcdir)perl/msgaccel-prepare
|
||||||
$(XGETTEXT) --default-domain=$(PACKAGE) \
|
$(XGETTEXT) --default-domain=$(PACKAGE) \
|
||||||
--directory=$(top_srcdir) \
|
--directory=$(top_srcdir) \
|
||||||
--add-comments --language=C \
|
--add-comments --language=C \
|
||||||
@ -77,7 +77,7 @@ $(srcdir)$(PACKAGE).pot: $(srcdir)$(POTFILES_ABS_LIST) $(srcdir)perl/gather-acce
|
|||||||
--flag=N__:1:pass-c-format \
|
--flag=N__:1:pass-c-format \
|
||||||
-f $(srcdir)$(POTFILES_ABS_LIST) \
|
-f $(srcdir)$(POTFILES_ABS_LIST) \
|
||||||
&& test -f $(PACKAGE).po \
|
&& test -f $(PACKAGE).po \
|
||||||
&& $(PERL) -I"$(srcdir)perl" $(srcdir)perl/gather-accelerator-contexts.pl -S"$(top_srcdir)" $(PACKAGE).po \
|
&& $(PERL) -I"$(srcdir)perl" $(srcdir)perl/msgaccel-prepare -S"$(top_srcdir)" $(PACKAGE).po \
|
||||||
&& mv -f $(PACKAGE).po $(srcdir)$(PACKAGE).pot
|
&& mv -f $(PACKAGE).po $(srcdir)$(PACKAGE).pot
|
||||||
|
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ check-po:
|
|||||||
@-$(foreach lang,$(basename $(if $(strip $(PO)),$(PO),$(GMOFILES))), \
|
@-$(foreach lang,$(basename $(if $(strip $(PO)),$(PO),$(GMOFILES))), \
|
||||||
echo -n "$(lang): "; \
|
echo -n "$(lang): "; \
|
||||||
$(GMSGFMT) --check --check-accelerators="~" --verbose --statistics -o /dev/null $(srcdir)$(lang).po; \
|
$(GMSGFMT) --check --check-accelerators="~" --verbose --statistics -o /dev/null $(srcdir)$(lang).po; \
|
||||||
$(PERL) -I"$(srcdir)perl" $(srcdir)perl/check-accelerator-conflicts.pl $(srcdir)$(lang).po; \
|
$(PERL) -I"$(srcdir)perl" $(srcdir)perl/msgaccel-check $(srcdir)$(lang).po; \
|
||||||
)
|
)
|
||||||
|
|
||||||
### Installation and distribution
|
### Installation and distribution
|
||||||
|
127
po/README
127
po/README
@ -166,131 +166,8 @@ well, especially Last-Translator and PO-Revision-Date fields.
|
|||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
First set Plural-Forms: header (msgid "" at top of .po file) to some correct
|
First set Plural-Forms: header (msgid "" at top of .po file) to some correct
|
||||||
value, depending on language.
|
value, depending on language. See GNU gettext documentation for details, at
|
||||||
|
http://www.gnu.org/software/gettext
|
||||||
To help you in this, here is an excerpt from GNU gettext documentation:
|
|
||||||
|
|
||||||
Only one form:
|
|
||||||
Some languages only require one single form. There is no distinction
|
|
||||||
between the singular and plural form. An appropriate header entry
|
|
||||||
would look like this:
|
|
||||||
|
|
||||||
Plural-Forms: nplurals=1; plural=0;
|
|
||||||
|
|
||||||
Languages with this property include:
|
|
||||||
|
|
||||||
Finno-Ugric family
|
|
||||||
Hungarian
|
|
||||||
Asian family
|
|
||||||
Japanese, Korean
|
|
||||||
Turkic/Altaic family
|
|
||||||
Turkish
|
|
||||||
|
|
||||||
Two forms, singular used for one only:
|
|
||||||
This is the form used in most existing programs since it is what English
|
|
||||||
is using. A header entry would look like this:
|
|
||||||
|
|
||||||
Plural-Forms: nplurals=2; plural=n != 1;
|
|
||||||
|
|
||||||
(Note: this uses the feature of C expressions that boolean expressions
|
|
||||||
have to value zero or one.)
|
|
||||||
|
|
||||||
Languages with this property include:
|
|
||||||
|
|
||||||
Germanic family
|
|
||||||
Danish, Dutch, English, German, Norwegian, Swedish
|
|
||||||
Finno-Ugric family
|
|
||||||
Estonian, Finnish
|
|
||||||
Latin/Greek family
|
|
||||||
Greek
|
|
||||||
Semitic family
|
|
||||||
Hebrew
|
|
||||||
Romanic family
|
|
||||||
Italian, Portuguese, Spanish
|
|
||||||
Artificial
|
|
||||||
Esperanto
|
|
||||||
|
|
||||||
Two forms, singular used for zero and one:
|
|
||||||
Exceptional case in the language family. The header entry would be:
|
|
||||||
|
|
||||||
Plural-Forms: nplurals=2; plural=n>1;
|
|
||||||
|
|
||||||
Languages with this property include:
|
|
||||||
|
|
||||||
Romanic family
|
|
||||||
French, Brazilian Portuguese
|
|
||||||
|
|
||||||
Three forms, special case for zero:
|
|
||||||
The header entry would be:
|
|
||||||
|
|
||||||
Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2;
|
|
||||||
|
|
||||||
Languages with this property include:
|
|
||||||
|
|
||||||
Baltic family
|
|
||||||
Latvian
|
|
||||||
|
|
||||||
Three forms, special cases for one and two:
|
|
||||||
The header entry would be:
|
|
||||||
|
|
||||||
Plural-Forms: nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2;
|
|
||||||
|
|
||||||
Languages with this property include:
|
|
||||||
|
|
||||||
Celtic
|
|
||||||
Gaeilge (Irish)
|
|
||||||
|
|
||||||
Three forms, special case for numbers ending in 1[2-9]:
|
|
||||||
The header entry would look like this:
|
|
||||||
|
|
||||||
Plural-Forms: nplurals=3; \
|
|
||||||
plural=n%10==1 && n%100!=11 ? 0 : \
|
|
||||||
n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2;
|
|
||||||
|
|
||||||
Languages with this property include:
|
|
||||||
|
|
||||||
Baltic family
|
|
||||||
Lithuanian
|
|
||||||
|
|
||||||
Three forms, special cases for numbers ending in 1 and 2, 3, 4,
|
|
||||||
except those ending in 1[1-4]:
|
|
||||||
The header entry would look like this:
|
|
||||||
|
|
||||||
Plural-Forms: nplurals=3; \
|
|
||||||
plural=n%10==1 && n%100!=11 ? 0 : \
|
|
||||||
n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;
|
|
||||||
|
|
||||||
Languages with this property include:
|
|
||||||
|
|
||||||
Slavic family
|
|
||||||
Croatian, Czech, Russian, Slovak, Ukrainian
|
|
||||||
|
|
||||||
Three forms, special case for one and some numbers ending in 2, 3, or 4:
|
|
||||||
The header entry would look like this:
|
|
||||||
|
|
||||||
Plural-Forms: nplurals=3; \
|
|
||||||
plural=n==1 ? 0 : \
|
|
||||||
n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;
|
|
||||||
|
|
||||||
Languages with this property include:
|
|
||||||
|
|
||||||
Slavic family
|
|
||||||
Polish
|
|
||||||
|
|
||||||
Four forms, special case for one and all numbers ending in 02, 03, or 04:
|
|
||||||
The header entry would look like this:
|
|
||||||
|
|
||||||
Plural-Forms: nplurals=4; \
|
|
||||||
plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3;
|
|
||||||
|
|
||||||
Languages with this property include:
|
|
||||||
|
|
||||||
Slavic family
|
|
||||||
Slovenian
|
|
||||||
|
|
||||||
|
|
||||||
More info at http://www.gnu.org/software/gettext
|
|
||||||
|
|
||||||
|
|
||||||
Plural forms will appear like this in .po file:
|
Plural forms will appear like this in .po file:
|
||||||
|
|
||||||
|
@ -21,21 +21,21 @@ When a programmer adds a translatable string to the C source code of
|
|||||||
ELinks, and the string contains an accelerator, he should also add a
|
ELinks, and the string contains an accelerator, he should also add a
|
||||||
special "gettext_accelerator_context" comment that names the menu or
|
special "gettext_accelerator_context" comment that names the menu or
|
||||||
dialog box in which the string will be used. See the documentation of
|
dialog box in which the string will be used. See the documentation of
|
||||||
gather-accelerator-contexts.pl for the details.
|
msgaccel-prepare for the details.
|
||||||
|
|
||||||
When a programmer or translator runs "make update-po" in the
|
When a programmer or translator runs "make update-po" in the elinks/po
|
||||||
elinks/po directory, gather-accelerator-contexts.pl reads the
|
directory, msgaccel-prepare reads the "gettext_accelerator_context"
|
||||||
"gettext_accelerator_context" comments in the source files and
|
comments in the source files and generates "accelerator_context"
|
||||||
generates "accelerator_context" comments in elinks.pot. Then,
|
comments in elinks.pot. Then, msgmerge copies them from elinks.pot to
|
||||||
msgmerge copies them from elinks.pot to *.po.
|
*.po.
|
||||||
|
|
||||||
When a translator edits a *.po file, she does not alter the
|
When a translator edits a *.po file, she does not alter the
|
||||||
"accelerator_context" comments.
|
"accelerator_context" comments.
|
||||||
|
|
||||||
When a translator runs "make check-po" in the elinks/po directory,
|
When a translator runs "make check-po" in the elinks/po directory,
|
||||||
check-accelerator-conflicts.pl reads the "accelerator_context"
|
msgaccel-check reads the "accelerator_context" comments in the *.po
|
||||||
comments in the *.po file, checks the accelerators in the
|
file, checks the accelerators in the translations, and displays any
|
||||||
translations, and displays any conflicts it finds.
|
conflicts it finds.
|
||||||
|
|
||||||
|
|
||||||
FILES
|
FILES
|
||||||
@ -43,12 +43,12 @@ FILES
|
|||||||
|
|
||||||
See each file for copying conditions.
|
See each file for copying conditions.
|
||||||
|
|
||||||
gather-accelerator-contexts.pl reads elinks.pot and the source files
|
msgaccel-prepare reads elinks.pot and the source files to which it
|
||||||
to which it refers, and writes a new elinks.pot with information from
|
refers, and writes a new elinks.pot with information from
|
||||||
"gettext_accelerator_context" comments.
|
"gettext_accelerator_context" comments.
|
||||||
|
|
||||||
check-accelerator-conflicts.pl reads just one *.po file and scans it
|
msgaccel-check reads just one *.po file and scans it for conflicts.
|
||||||
for conflicts. It does not access the C source files.
|
It does not access the C source files.
|
||||||
|
|
||||||
Locale/PO.pm was originally imported from Locale-PO-0.16 on CPAN, and
|
Locale/PO.pm was originally imported from Locale-PO-0.16 on CPAN, and
|
||||||
has since been patched to make it more suitable for these scripts.
|
has since been patched to make it more suitable for these scripts.
|
||||||
|
@ -7,11 +7,11 @@ use Locale::PO qw();
|
|||||||
use Getopt::Long qw(GetOptions :config bundling gnu_compat);
|
use Getopt::Long qw(GetOptions :config bundling gnu_compat);
|
||||||
use autouse 'Pod::Usage' => qw(pod2usage);
|
use autouse 'Pod::Usage' => qw(pod2usage);
|
||||||
|
|
||||||
my $VERSION = "1.5";
|
my $VERSION = "1.6";
|
||||||
|
|
||||||
sub show_version
|
sub show_version
|
||||||
{
|
{
|
||||||
print "check-accelerator-conflicts.pl $VERSION\n";
|
print "msgaccel-check $VERSION\n";
|
||||||
pod2usage({-verbose => 99, -sections => "COPYRIGHT AND LICENSE",
|
pod2usage({-verbose => 99, -sections => "COPYRIGHT AND LICENSE",
|
||||||
-exitval => 0});
|
-exitval => 0});
|
||||||
}
|
}
|
||||||
@ -208,32 +208,31 @@ __END__
|
|||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
|
||||||
check-accelerator-conflicts.pl - Scan a PO file for conflicting
|
msgaccel-check - Scan a PO file for conflicting accelerator keys.
|
||||||
accelerator keys.
|
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
B<check-accelerator-conflicts.pl> [I<option> ...] F<I<language>.po> [...]
|
B<msgaccel-check> [I<option> ...] F<I<language>.po> [...]
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
B<check-accelerator-conflicts.pl> is part of a framework that detects
|
B<msgaccel-check> is part of a framework that detects conflicting
|
||||||
conflicting accelerator keys in Gettext PO files. A conflict is when
|
accelerator keys in Gettext PO files. A conflict is when two items in
|
||||||
two items in the same menu or two buttons in the same dialog box use
|
the same menu or two buttons in the same dialog box use the same
|
||||||
the same accelerator key.
|
accelerator key.
|
||||||
|
|
||||||
The PO file format does not normally include any information on which
|
The PO file format does not normally include any information on which
|
||||||
strings will be used in the same menu or dialog box.
|
strings will be used in the same menu or dialog box.
|
||||||
B<check-accelerator-conflicts.pl> can only be used on PO files to which
|
B<msgaccel-check> can only be used on PO files to which this
|
||||||
this information has been added with B<gather-accelerator-contexts.pl>
|
information has been added with B<msgaccel-prepare> or merged with
|
||||||
or merged with B<msgmerge>.
|
B<msgmerge>.
|
||||||
|
|
||||||
B<check-accelerator-conflicts.pl> reads the F<I<language>.po> file
|
B<msgaccel-check> reads the F<I<language>.po> file named on the
|
||||||
named on the command line and reports any conflicts to standard error.
|
command line and reports any conflicts to standard error. It also
|
||||||
It also tries to suggest replacements for the conflicting accelerators.
|
tries to suggest replacements for the conflicting accelerators.
|
||||||
|
|
||||||
B<check-accelerator-conflicts.pl> does not access the source files to
|
B<msgaccel-check> does not access the source files to which
|
||||||
which F<I<language>.po> refers. Thus, it does not matter if the line
|
F<I<language>.po> refers. Thus, it does not matter if the line
|
||||||
numbers in "#:" lines are out of date.
|
numbers in "#:" lines are out of date.
|
||||||
|
|
||||||
=head1 OPTIONS
|
=head1 OPTIONS
|
||||||
@ -243,10 +242,9 @@ numbers in "#:" lines are out of date.
|
|||||||
=item B<--accelerator-tag=>I<character>
|
=item B<--accelerator-tag=>I<character>
|
||||||
|
|
||||||
Specify the character that marks accelerators in C<msgstr> strings.
|
Specify the character that marks accelerators in C<msgstr> strings.
|
||||||
Whenever this character occurs in a C<msgstr>,
|
Whenever this character occurs in a C<msgstr>, B<msgaccel-check>
|
||||||
B<check-accelerator-conflicts.pl> treats the next character as an
|
treats the next character as an accelerator and checks that it is
|
||||||
accelerator and checks that it is unique in each of the contexts in
|
unique in each of the contexts in which the C<msgstr> is used.
|
||||||
which the C<msgstr> is used.
|
|
||||||
|
|
||||||
Omitting the B<--accelerator-tag> option implies
|
Omitting the B<--accelerator-tag> option implies
|
||||||
B<--accelerator-tag="~">. The option must be given to each program
|
B<--accelerator-tag="~">. The option must be given to each program
|
||||||
@ -258,14 +256,13 @@ in the PO file.
|
|||||||
=item B<--no-msgid-fallback>
|
=item B<--no-msgid-fallback>
|
||||||
|
|
||||||
Select how to check entries where the C<msgstr> is missing or fuzzy.
|
Select how to check entries where the C<msgstr> is missing or fuzzy.
|
||||||
The default is B<--msgid-fallback>, which makes
|
The default is B<--msgid-fallback>, which makes B<msgaccel-check> use
|
||||||
B<check-accelerator-conflicts.pl> use the C<msgid> instead, and report
|
the C<msgid> instead, and report any conflicts between C<msgid> and
|
||||||
any conflicts between C<msgid> and C<msgstr> strings. The alternative
|
C<msgstr> strings. The alternative is B<--no-msgid-fallback>, which
|
||||||
is B<--no-msgid-fallback>, which makes B<check-accelerator-conflicts.pl>
|
makes B<msgaccel-check> completely ignore such entries.
|
||||||
completely ignore such entries.
|
|
||||||
|
|
||||||
Regardless of these options, B<check-accelerator-conflicts.pl> will
|
Regardless of these options, B<msgaccel-check> will suggest
|
||||||
suggest accelerators that would conflict with ones defined in C<msgid>
|
accelerators that would conflict with ones defined in C<msgid>
|
||||||
strings. Those strings will be eventually shadowed by C<msgstr>
|
strings. Those strings will be eventually shadowed by C<msgstr>
|
||||||
strings, so their accelerators should not affect which accelerators
|
strings, so their accelerators should not affect which accelerators
|
||||||
the translator chooses for C<msgstr> strings.
|
the translator chooses for C<msgstr> strings.
|
||||||
@ -278,8 +275,8 @@ the translator chooses for C<msgstr> strings.
|
|||||||
|
|
||||||
=item F<I<language>.po> [...]
|
=item F<I<language>.po> [...]
|
||||||
|
|
||||||
The PO files to be scanned for conflicts. These files must include the
|
The PO files to be scanned for conflicts. These files must include
|
||||||
"accelerator_context" comments added by B<gather-accelerator-contexts.pl>.
|
the "accelerator_context" comments added by B<msgaccel-prepare>.
|
||||||
If the special comments are missing, no conflicts will be found.
|
If the special comments are missing, no conflicts will be found.
|
||||||
|
|
||||||
=back
|
=back
|
||||||
@ -296,9 +293,9 @@ If the special comments are missing, no conflicts will be found.
|
|||||||
|
|
||||||
=head2 Waiting for Locale::PO fixes
|
=head2 Waiting for Locale::PO fixes
|
||||||
|
|
||||||
When B<check-accelerator-conflicts.pl> includes C<msgstr> strings in
|
When B<msgaccel-check> includes C<msgstr> strings in warnings, it
|
||||||
warnings, it should transcode them from the charset of the PO file to
|
should transcode them from the charset of the PO file to the one
|
||||||
the one specified by the user's locale.
|
specified by the user's locale.
|
||||||
|
|
||||||
=head1 AUTHOR
|
=head1 AUTHOR
|
||||||
|
|
||||||
@ -335,4 +332,4 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
|
|
||||||
=head1 SEE ALSO
|
=head1 SEE ALSO
|
||||||
|
|
||||||
L<gather-accelerator-contexts.pl>, C<xgettext(1)>, C<msgmerge(1)>
|
L<msgaccel-prepare>, C<xgettext(1)>, C<msgmerge(1)>
|
@ -8,11 +8,11 @@ use Getopt::Long qw(GetOptions :config bundling gnu_compat);
|
|||||||
use autouse 'Pod::Usage' => qw(pod2usage);
|
use autouse 'Pod::Usage' => qw(pod2usage);
|
||||||
use autouse 'File::Spec::Functions' => qw(catfile);
|
use autouse 'File::Spec::Functions' => qw(catfile);
|
||||||
|
|
||||||
my $VERSION = "1.1";
|
my $VERSION = "1.2";
|
||||||
|
|
||||||
sub show_version
|
sub show_version
|
||||||
{
|
{
|
||||||
print "gather-accelerator-contexts.pl $VERSION\n";
|
print "msgaccel-prepare $VERSION\n";
|
||||||
pod2usage({-verbose => 99, -sections => "COPYRIGHT AND LICENSE",
|
pod2usage({-verbose => 99, -sections => "COPYRIGHT AND LICENSE",
|
||||||
-exitval => 0});
|
-exitval => 0});
|
||||||
}
|
}
|
||||||
@ -168,24 +168,24 @@ __END__
|
|||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
|
||||||
gather-accelerator-contexts.pl - Augment a PO file with information
|
msgaccel-prepare - Augment a PO file with information for detecting
|
||||||
for detecting accelerator conflicts.
|
accelerator conflicts.
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
B<gather-accelerator-contexts.pl> [I<option> ...] F<I<program>.pot>
|
B<msgaccel-prepare> [I<option> ...] F<I<program>.pot>
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
B<gather-accelerator-contexts.pl> is part of a framework that detects
|
B<msgaccel-prepare> is part of a framework that detects conflicting
|
||||||
conflicting accelerator keys in Gettext PO files. A conflict is when
|
accelerator keys in Gettext PO files. A conflict is when two items in
|
||||||
two items in the same menu or two buttons in the same dialog box use
|
the same menu or two buttons in the same dialog box use the same
|
||||||
the same accelerator key.
|
accelerator key.
|
||||||
|
|
||||||
The PO file format does not normally include any information on which
|
The PO file format does not normally include any information
|
||||||
strings will be used in the same menu or dialog box.
|
on which strings will be used in the same menu or dialog box.
|
||||||
B<gather-accelerator-contexts.pl> adds this information in the form of
|
B<msgaccel-prepare> adds this information in the form of
|
||||||
"accelerator_context" comments, which B<check-accelerator-conflicts.pl>
|
"accelerator_context" comments, which B<msgaccel-check>
|
||||||
then parses in order to detect the conflicts.
|
then parses in order to detect the conflicts.
|
||||||
|
|
||||||
The PO file format also does not directly support definitions of
|
The PO file format also does not directly support definitions of
|
||||||
@ -194,17 +194,17 @@ strings, by placing a tilde in front of the character that should be
|
|||||||
used as the accelerator key. That is also the syntax supported by
|
used as the accelerator key. That is also the syntax supported by
|
||||||
this framework and by B<msgfmt --check-accelerators> of GNU Gettext.
|
this framework and by B<msgfmt --check-accelerators> of GNU Gettext.
|
||||||
|
|
||||||
B<gather-accelerator-contexts.pl> first reads the F<I<program>.pot>
|
B<msgaccel-prepare> first reads the F<I<program>.pot> file named on
|
||||||
file named on the command line. This file must include "#:" comments
|
the command line. This file must include "#:" comments that point
|
||||||
that point to the source files from which B<xgettext> extracted each
|
to the source files from which B<xgettext> extracted each C<msgid>.
|
||||||
C<msgid>. B<gather-accelerator-contexts.pl> then scans those source
|
B<msgaccel-prepare> then scans those source files for context
|
||||||
files for context information and rewrites F<I<program>.pot> to
|
information and rewrites F<I<program>.pot> to include the
|
||||||
include the "accelerator_context" comments. Finally, the standard
|
"accelerator_context" comments. Finally, the standard tool
|
||||||
tool B<msgmerge> can be used to copy the added comments to all the
|
B<msgmerge> can be used to copy the added comments to all the
|
||||||
F<I<language>.po> files.
|
F<I<language>.po> files.
|
||||||
|
|
||||||
It is best to run B<gather-accelerator-contexts.pl> immediately after
|
It is best to run B<msgaccel-prepare> immediately after B<xgettext>
|
||||||
B<xgettext> so that the source references will be up to date.
|
so that the source references will be up to date.
|
||||||
|
|
||||||
=head2 Contexts
|
=head2 Contexts
|
||||||
|
|
||||||
@ -249,17 +249,16 @@ formatted like this:
|
|||||||
[gettext_accelerator_context()]
|
[gettext_accelerator_context()]
|
||||||
ends the region. */
|
ends the region. */
|
||||||
|
|
||||||
B<gather-accelerator-contexts.pl> removes from F<I<program>.pot> any
|
B<msgaccel-prepare> removes from F<I<program>.pot> any
|
||||||
"gettext_accelerator_context" comments that B<xgettext --add-comments>
|
"gettext_accelerator_context" comments that B<xgettext --add-comments>
|
||||||
may have copied there.
|
may have copied there.
|
||||||
|
|
||||||
B<gather-accelerator-contexts.pl> warns if it does not find any
|
B<msgaccel-prepare> warns if it does not find any contexts for some
|
||||||
contexts for some use of an C<msgid> that contains the character
|
use of an C<msgid> that contains the character specified with the
|
||||||
specified with the B<--accelerator-tag> option. If the character does
|
B<--accelerator-tag> option. If the character does not actually
|
||||||
not actually indicate an accelerator in that C<msgid> (e.g. "~" in
|
indicate an accelerator in that C<msgid> (e.g. "~" in "~/.bashrc"),
|
||||||
"~/.bashrc"), the warning can be silenced by specifying the special
|
the warning can be silenced by specifying the special context
|
||||||
context "IGNORE", which B<gather-accelerator-contexts.pl> otherwise
|
"IGNORE", which B<msgaccel-prepare> otherwise ignores.
|
||||||
ignores.
|
|
||||||
|
|
||||||
=head1 OPTIONS
|
=head1 OPTIONS
|
||||||
|
|
||||||
@ -270,15 +269,14 @@ B<--source-directory=>F<I<srcdir>>
|
|||||||
|
|
||||||
The directory to which the source references in "#:" lines are
|
The directory to which the source references in "#:" lines are
|
||||||
relative. Each use of this option adds one directory to the search
|
relative. Each use of this option adds one directory to the search
|
||||||
path. If you do not specify this option,
|
path. If you do not specify this option, B<msgaccel-prepare>
|
||||||
B<gather-accelerator-contexts.pl> implicitly searches the current
|
implicitly searches the current directory.
|
||||||
directory.
|
|
||||||
|
|
||||||
=item B<--accelerator-tag=>I<character>
|
=item B<--accelerator-tag=>I<character>
|
||||||
|
|
||||||
Specify the character that marks accelerators in C<msgid> strings.
|
Specify the character that marks accelerators in C<msgid> strings.
|
||||||
B<gather-accelerator-contexts.pl> looks up accelerator contexts for
|
B<msgaccel-prepare> looks up accelerator contexts for any C<msgid>
|
||||||
any C<msgid> that contains this character.
|
that contains this character.
|
||||||
|
|
||||||
Omitting the B<--accelerator-tag> option implies
|
Omitting the B<--accelerator-tag> option implies
|
||||||
B<--accelerator-tag="~">. The option must be given to each program
|
B<--accelerator-tag="~">. The option must be given to each program
|
||||||
@ -293,24 +291,23 @@ in the PO file.
|
|||||||
|
|
||||||
=item F<I<program>.pot>
|
=item F<I<program>.pot>
|
||||||
|
|
||||||
The file to augment with context information.
|
The file to augment with context information. B<msgaccel-prepare>
|
||||||
B<gather-accelerator-contexts.pl> first reads this file and then
|
first reads this file and then overwrites it.
|
||||||
overwrites it.
|
|
||||||
|
|
||||||
Although this documentation keeps referring to F<I<program>.pot>,
|
Although this documentation keeps referring to F<I<program>.pot>,
|
||||||
you can also use B<gather-accelerator-contexts.pl> on an already
|
you can also use B<msgaccel-prepare> on an already translated
|
||||||
translated F<I<language>.po>. However, that will only work correctly
|
F<I<language>.po>. However, that will only work correctly if the
|
||||||
if the source references in the "#:" lines are still up to date.
|
source references in the "#:" lines are still up to date.
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
=head1 BUGS
|
=head1 BUGS
|
||||||
|
|
||||||
B<gather-accelerator-contexts.pl> assumes that source files are in
|
B<msgaccel-prepare> assumes that source files are in the C programming
|
||||||
the C programming language: specifically, that a closing brace at
|
language: specifically, that a closing brace at the beginning of a
|
||||||
the beginning of a line marks the end of a function.
|
line marks the end of a function.
|
||||||
|
|
||||||
B<gather-accelerator-contexts.pl> doesn't check whether the
|
B<msgaccel-prepare> doesn't check whether the
|
||||||
"gettext_accelerator_context" comments actually are comments.
|
"gettext_accelerator_context" comments actually are comments.
|
||||||
|
|
||||||
=head1 AUTHOR
|
=head1 AUTHOR
|
||||||
@ -348,4 +345,4 @@ DEALINGS IN THE SOFTWARE.
|
|||||||
|
|
||||||
=head1 SEE ALSO
|
=head1 SEE ALSO
|
||||||
|
|
||||||
L<check-accelerator-conflicts.pl>, C<xgettext(1)>, C<msgmerge(1)>
|
L<msgaccel-check>, C<xgettext(1)>, C<msgmerge(1)>
|
@ -111,8 +111,14 @@ get_home(void)
|
|||||||
{
|
{
|
||||||
unsigned char *home_elinks;
|
unsigned char *home_elinks;
|
||||||
unsigned char *envhome = getenv("HOME");
|
unsigned char *envhome = getenv("HOME");
|
||||||
unsigned char *home = envhome ? stracpy(envhome)
|
unsigned char *home = NULL;
|
||||||
: elinks_dirname(program.path);
|
|
||||||
|
if (!home && envhome)
|
||||||
|
home = stracpy(envhome);
|
||||||
|
if (!home)
|
||||||
|
home = user_appdata_directory();
|
||||||
|
if (!home)
|
||||||
|
home = elinks_dirname(program.path);
|
||||||
|
|
||||||
if (home)
|
if (home)
|
||||||
strip_trailing_dir_sep(home);
|
strip_trailing_dir_sep(home);
|
||||||
|
@ -90,12 +90,23 @@ ride_on:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
skip_css_block(struct scanner *scanner)
|
||||||
|
{
|
||||||
|
if (skip_css_tokens(scanner, '{')) {
|
||||||
|
const int preclimit = get_css_precedence('}');
|
||||||
|
int depth = 1;
|
||||||
|
struct scanner_token *token = get_scanner_token(scanner);
|
||||||
|
|
||||||
/* TODO: We should handle support for skipping blocks better like "{ { } }"
|
while (token && token->precedence <= preclimit && depth > 0) {
|
||||||
* will be handled correctly. --jonas */
|
if (token->type == '{')
|
||||||
#define skip_css_block(scanner) \
|
++depth;
|
||||||
if (skip_css_tokens(scanner, '{')) skip_css_tokens(scanner, '}');
|
else if (token->type == '}')
|
||||||
|
--depth;
|
||||||
|
token = get_next_scanner_token(scanner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Atrules grammer:
|
/* Atrules grammer:
|
||||||
*
|
*
|
||||||
|
@ -1108,7 +1108,13 @@ justify_line(struct html_context *html_context, int y)
|
|||||||
int prev_end = 0;
|
int prev_end = 0;
|
||||||
int word;
|
int word;
|
||||||
|
|
||||||
clear_hchars(html_context, 0, y, overlap(par_format));
|
/* Allocate enough memory for the justified line.
|
||||||
|
* If the memory is not available, then leave the
|
||||||
|
* line unchanged, rather than halfway there. The
|
||||||
|
* following loop assumes the allocation succeeded. */
|
||||||
|
if (!realloc_line(html_context, html_context->part->document,
|
||||||
|
Y(y), X(overlap(par_format))))
|
||||||
|
goto out_of_memory;
|
||||||
|
|
||||||
for (word = 0; word < spaces; word++) {
|
for (word = 0; word < spaces; word++) {
|
||||||
/* We have to increase line length by 'diff' num. of
|
/* We have to increase line length by 'diff' num. of
|
||||||
@ -1122,14 +1128,40 @@ justify_line(struct html_context *html_context, int y)
|
|||||||
|
|
||||||
assert(word_len >= 0);
|
assert(word_len >= 0);
|
||||||
if_assert_failed continue;
|
if_assert_failed continue;
|
||||||
if (!word_len) continue;
|
|
||||||
|
|
||||||
word_shift = (word * diff) / (spaces - 1);
|
word_shift = (word * diff) / (spaces - 1);
|
||||||
new_start = word_start + word_shift;
|
new_start = word_start + word_shift;
|
||||||
|
|
||||||
|
/* Copy the original word, without any spaces. */
|
||||||
copy_chars(html_context, new_start, y, word_len,
|
copy_chars(html_context, new_start, y, word_len,
|
||||||
&line[word_start]);
|
&line[word_start]);
|
||||||
|
|
||||||
|
/* Copy the space that preceded the word,
|
||||||
|
* duplicating it as many times as necessary.
|
||||||
|
* This preserves its attributes, such as
|
||||||
|
* background color and underlining. If this
|
||||||
|
* is the first word, then skip the copy
|
||||||
|
* because there might not be a space there
|
||||||
|
* and anyway it need not be duplicated. */
|
||||||
|
if (word) {
|
||||||
|
int spacex;
|
||||||
|
|
||||||
|
/* realloc_line() was called above. */
|
||||||
|
assert(LEN(y) >= new_start);
|
||||||
|
if_assert_failed continue;
|
||||||
|
|
||||||
|
for (spacex = prev_end; spacex < new_start;
|
||||||
|
++spacex) {
|
||||||
|
copy_screen_chars(&POS(spacex, y),
|
||||||
|
&line[word_start - 1],
|
||||||
|
1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remember that any links at the right side
|
||||||
|
* of the added spaces have moved, and the
|
||||||
|
* spaces themselves may also belong to a
|
||||||
|
* link. */
|
||||||
new_spaces = new_start - prev_end - 1;
|
new_spaces = new_start - prev_end - 1;
|
||||||
if (word && new_spaces) {
|
if (word && new_spaces) {
|
||||||
move_links(html_context, prev_end + 1, y, new_start, y);
|
move_links(html_context, prev_end + 1, y, new_start, y);
|
||||||
@ -1141,6 +1173,7 @@ justify_line(struct html_context *html_context, int y)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out_of_memory:
|
||||||
fmem_free(space_list);
|
fmem_free(space_list);
|
||||||
fmem_free(line);
|
fmem_free(line);
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,9 @@
|
|||||||
#ifdef HAVE_UNISTD_H
|
#ifdef HAVE_UNISTD_H
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_WS2TCPIP_H
|
||||||
|
#include <ws2tcpip.h> /* socklen_t for MinGW */
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_GETIFADDRS
|
#ifdef HAVE_GETIFADDRS
|
||||||
#ifdef HAVE_NETDB_H
|
#ifdef HAVE_NETDB_H
|
||||||
|
@ -75,4 +75,8 @@ unsigned char *get_shell(void);
|
|||||||
* available at all. Face it, we are just cool. */
|
* available at all. Face it, we are just cool. */
|
||||||
void elinks_cfmakeraw(struct termios *t);
|
void elinks_cfmakeraw(struct termios *t);
|
||||||
|
|
||||||
|
#ifndef user_appdata_directory
|
||||||
|
#define user_appdata_directory() NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -4,7 +4,11 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Get SHGFP_TYPE_CURRENT from <shlobj.h>. */
|
||||||
|
#define _WIN32_IE 0x500
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <shlobj.h>
|
||||||
|
|
||||||
#include "osdep/system.h"
|
#include "osdep/system.h"
|
||||||
|
|
||||||
@ -258,3 +262,21 @@ gettext__parse(void *arg)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
unsigned char *
|
||||||
|
user_appdata_directory(void)
|
||||||
|
{
|
||||||
|
#if _WIN32_WINNT >= 0x0500
|
||||||
|
HWND hwnd = GetConsoleWindow();
|
||||||
|
#else
|
||||||
|
HWND hwnd = NULL;
|
||||||
|
#endif
|
||||||
|
char path[MAX_PATH];
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
hr = SHGetFolderPath(hwnd, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, path);
|
||||||
|
if (hr == S_OK) /* Don't even allow S_FALSE. */
|
||||||
|
return stracpy(path);
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
@ -13,6 +13,8 @@ struct terminal;
|
|||||||
|
|
||||||
void open_in_new_win32(struct terminal *term, unsigned char *exe_name,
|
void open_in_new_win32(struct terminal *term, unsigned char *exe_name,
|
||||||
unsigned char *param);
|
unsigned char *param);
|
||||||
|
unsigned char *user_appdata_directory(void);
|
||||||
|
#define user_appdata_directory user_appdata_directory
|
||||||
|
|
||||||
|
|
||||||
/* Stub functions: */
|
/* Stub functions: */
|
||||||
|
@ -10,7 +10,7 @@ SUBDIRS-$(CONFIG_NNTP) += nntp
|
|||||||
SUBDIRS-$(CONFIG_SMB) += smb
|
SUBDIRS-$(CONFIG_SMB) += smb
|
||||||
SUBDIRS-$(CONFIG_URI_REWRITE) += rewrite
|
SUBDIRS-$(CONFIG_URI_REWRITE) += rewrite
|
||||||
|
|
||||||
SUBDIRS = auth file http
|
SUBDIRS = auth file http test
|
||||||
|
|
||||||
OBJS-$(CONFIG_DATA) += data.o
|
OBJS-$(CONFIG_DATA) += data.o
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ add_dir_entry(struct directory_entry *entry, struct string *page,
|
|||||||
add_string_to_string(page, &uri_encoded_name);
|
add_string_to_string(page, &uri_encoded_name);
|
||||||
|
|
||||||
if (entry->attrib[0] == 'd') {
|
if (entry->attrib[0] == 'd') {
|
||||||
add_char_to_string(page, CHAR_DIR_SEP);
|
add_char_to_string(page, '/');
|
||||||
|
|
||||||
#ifdef FS_UNIX_SOFTLINKS
|
#ifdef FS_UNIX_SOFTLINKS
|
||||||
} else if (entry->attrib[0] == 'l') {
|
} else if (entry->attrib[0] == 'l') {
|
||||||
@ -271,7 +271,10 @@ file_protocol_handler(struct connection *connection)
|
|||||||
|
|
||||||
decode_uri_string(&name);
|
decode_uri_string(&name);
|
||||||
|
|
||||||
if (file_is_dir(name.source)) {
|
/* In Win32, file_is_dir seems to always return 0 if the name
|
||||||
|
* ends with a directory separator. */
|
||||||
|
if ((name.length > 0 && dir_sep(name.source[name.length - 1]))
|
||||||
|
|| file_is_dir(name.source)) {
|
||||||
/* In order for global history and directory listing to
|
/* In order for global history and directory listing to
|
||||||
* function properly the directory url must end with a
|
* function properly the directory url must end with a
|
||||||
* directory separator. */
|
* directory separator. */
|
||||||
|
16
src/protocol/test/Makefile
Normal file
16
src/protocol/test/Makefile
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
top_builddir=../../..
|
||||||
|
include $(top_builddir)/Makefile.config
|
||||||
|
|
||||||
|
TEST_PROGS = \
|
||||||
|
test_uri
|
||||||
|
|
||||||
|
TESTDEPS = \
|
||||||
|
$(top_builddir)/src/protocol/protocol.o \
|
||||||
|
$(top_builddir)/src/protocol/uri.o \
|
||||||
|
stub.o
|
||||||
|
|
||||||
|
CLEAN = stub.o
|
||||||
|
|
||||||
|
test_uri:: stub.o
|
||||||
|
|
||||||
|
include $(top_srcdir)/Makefile.lib
|
6
src/protocol/test/harness.h
Normal file
6
src/protocol/test/harness.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef EL__PROTOCOL_TEST_HARNESS_H
|
||||||
|
#define EL__PROTOCOL_TEST_HARNESS_H
|
||||||
|
|
||||||
|
void test_failed();
|
||||||
|
|
||||||
|
#endif
|
109
src/protocol/test/stub.c
Normal file
109
src/protocol/test/stub.c
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "elinks.h"
|
||||||
|
|
||||||
|
#include "bfu/msgbox.h"
|
||||||
|
#include "main/module.h"
|
||||||
|
#include "protocol/test/harness.h"
|
||||||
|
#include "protocol/user.h"
|
||||||
|
#include "session/session.h"
|
||||||
|
|
||||||
|
#define STUB_MODULE(name) \
|
||||||
|
struct module name = struct_module( \
|
||||||
|
/* name: */ "Stub " #name, \
|
||||||
|
/* options: */ NULL, \
|
||||||
|
/* hooks: */ NULL, \
|
||||||
|
/* submodules: */ NULL, \
|
||||||
|
/* data: */ NULL, \
|
||||||
|
/* init: */ NULL, \
|
||||||
|
/* done: */ NULL \
|
||||||
|
)
|
||||||
|
STUB_MODULE(auth_module);
|
||||||
|
STUB_MODULE(bittorrent_protocol_module);
|
||||||
|
STUB_MODULE(cgi_protocol_module);
|
||||||
|
STUB_MODULE(file_protocol_module);
|
||||||
|
STUB_MODULE(finger_protocol_module);
|
||||||
|
STUB_MODULE(fsp_protocol_module);
|
||||||
|
STUB_MODULE(ftp_protocol_module);
|
||||||
|
STUB_MODULE(gopher_protocol_module);
|
||||||
|
STUB_MODULE(http_protocol_module);
|
||||||
|
STUB_MODULE(nntp_protocol_module);
|
||||||
|
STUB_MODULE(smb_protocol_module);
|
||||||
|
STUB_MODULE(uri_rewrite_module);
|
||||||
|
STUB_MODULE(user_protocol_module);
|
||||||
|
|
||||||
|
static void
|
||||||
|
stub_called(const unsigned char *fun)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "FAIL: stub %s\n", fun);
|
||||||
|
test_failed();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define STUB_PROTOCOL_HANDLER(name) \
|
||||||
|
void \
|
||||||
|
name(struct connection *conn) \
|
||||||
|
{ \
|
||||||
|
stub_called(#name); \
|
||||||
|
} \
|
||||||
|
protocol_handler_T name /* consume semicolon */
|
||||||
|
#define STUB_PROTOCOL_EXTERNAL_HANDLER(name) \
|
||||||
|
void \
|
||||||
|
name(struct session *ses, struct uri *uri) \
|
||||||
|
{ \
|
||||||
|
stub_called(#name); \
|
||||||
|
} \
|
||||||
|
protocol_external_handler_T name /* consume semicolon */
|
||||||
|
STUB_PROTOCOL_HANDLER(about_protocol_handler);
|
||||||
|
STUB_PROTOCOL_HANDLER(bittorrent_protocol_handler);
|
||||||
|
STUB_PROTOCOL_HANDLER(data_protocol_handler);
|
||||||
|
STUB_PROTOCOL_EXTERNAL_HANDLER(ecmascript_protocol_handler);
|
||||||
|
STUB_PROTOCOL_HANDLER(file_protocol_handler);
|
||||||
|
STUB_PROTOCOL_HANDLER(finger_protocol_handler);
|
||||||
|
STUB_PROTOCOL_HANDLER(fsp_protocol_handler);
|
||||||
|
STUB_PROTOCOL_HANDLER(ftp_protocol_handler);
|
||||||
|
STUB_PROTOCOL_HANDLER(gopher_protocol_handler);
|
||||||
|
STUB_PROTOCOL_HANDLER(http_protocol_handler);
|
||||||
|
STUB_PROTOCOL_HANDLER(news_protocol_handler);
|
||||||
|
STUB_PROTOCOL_HANDLER(nntp_protocol_handler);
|
||||||
|
STUB_PROTOCOL_HANDLER(proxy_protocol_handler);
|
||||||
|
STUB_PROTOCOL_HANDLER(smb_protocol_handler);
|
||||||
|
STUB_PROTOCOL_EXTERNAL_HANDLER(user_protocol_handler);
|
||||||
|
|
||||||
|
/* declared in "protocol/user.h" */
|
||||||
|
unsigned char *
|
||||||
|
get_user_program(struct terminal *term, unsigned char *progid, int progidlen)
|
||||||
|
{
|
||||||
|
stub_called("get_user_program");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* declared in "session/session.h" */
|
||||||
|
void
|
||||||
|
print_error_dialog(struct session *ses, enum connection_state state,
|
||||||
|
struct uri *uri, enum connection_priority priority)
|
||||||
|
{
|
||||||
|
stub_called("print_error_dialog");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* declared in "bfu/msgbox.h" */
|
||||||
|
unsigned char *
|
||||||
|
msg_text(struct terminal *term, unsigned char *format, ...)
|
||||||
|
{
|
||||||
|
stub_called("msg_text");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* declared in "bfu/msgbox.h" */
|
||||||
|
struct dialog_data *
|
||||||
|
msg_box(struct terminal *term, struct memory_list *mem_list,
|
||||||
|
enum msgbox_flags flags, unsigned char *title, enum format_align align,
|
||||||
|
unsigned char *text, void *udata, int buttons, ...)
|
||||||
|
{
|
||||||
|
/* mem_list should be freed here but because this is just a
|
||||||
|
* test program it won't matter. */
|
||||||
|
stub_called("msg_box");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
2
src/protocol/test/test-uri
Normal file
2
src/protocol/test/test-uri
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#! /bin/sh -e
|
||||||
|
./test_uri
|
142
src/protocol/test/test_uri.c
Normal file
142
src/protocol/test/test_uri.c
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "elinks.h"
|
||||||
|
|
||||||
|
#include "protocol/test/harness.h"
|
||||||
|
#include "protocol/uri.h"
|
||||||
|
#include "util/string.h"
|
||||||
|
|
||||||
|
static int failures = 0;
|
||||||
|
static int successes = 0;
|
||||||
|
|
||||||
|
void
|
||||||
|
test_failed(void)
|
||||||
|
{
|
||||||
|
++failures;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_succeeded(void)
|
||||||
|
{
|
||||||
|
++successes;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_1_normalize_uri(const unsigned char *orig, const unsigned char *good)
|
||||||
|
{
|
||||||
|
struct string s;
|
||||||
|
unsigned char *norm;
|
||||||
|
|
||||||
|
if (!init_string(&s)) {
|
||||||
|
fputs("FAIL: init_string\n", stderr);
|
||||||
|
test_failed();
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (!add_to_string(&s, orig)) {
|
||||||
|
fputs("FAIL: add_to_string\n", stderr);
|
||||||
|
test_failed();
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
norm = normalize_uri(NULL, s.source);
|
||||||
|
if (norm == NULL) {
|
||||||
|
fprintf(stderr, "FAIL: normalize_uri NULL %s\n", orig);
|
||||||
|
test_failed();
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (strcmp(norm, good) != 0) {
|
||||||
|
fprintf(stderr, "FAIL: normalize_uri mismatch:\n"
|
||||||
|
"\toriginal: %s\n"
|
||||||
|
"\tresult: %s\n"
|
||||||
|
"\texpected: %s\n",
|
||||||
|
orig, norm, good);
|
||||||
|
test_failed();
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
test_succeeded();
|
||||||
|
|
||||||
|
out:
|
||||||
|
done_string(&s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_normalize_uri(void)
|
||||||
|
{
|
||||||
|
static const struct {
|
||||||
|
unsigned char *orig;
|
||||||
|
unsigned char *norm;
|
||||||
|
} tests[] = {
|
||||||
|
{ "http://example.org/foo/bar/baz?a=1&b=2#frag",
|
||||||
|
"http://example.org/foo/bar/baz?a=1&b=2#frag" },
|
||||||
|
{ "http://example.org/foo/bar/../?a=1&b=2#frag",
|
||||||
|
"http://example.org/foo/?a=1&b=2#frag" },
|
||||||
|
{ "http://example.org/foo/bar/../../baz?a=1&b=2#frag",
|
||||||
|
"http://example.org/baz?a=1&b=2#frag" },
|
||||||
|
{ "http://example.org/foo/bar/..",
|
||||||
|
"http://example.org/foo/" },
|
||||||
|
{ "http://example.org/foo/bar;a=1/..",
|
||||||
|
"http://example.org/foo/" },
|
||||||
|
{ "http://example.org/foo/bar..",
|
||||||
|
"http://example.org/foo/bar.." },
|
||||||
|
|
||||||
|
/* Bug 744 - ELinks changes "//" to "/" in path
|
||||||
|
* component of URI */
|
||||||
|
{ "http://example.org/foo/bar/baz",
|
||||||
|
"http://example.org/foo/bar/baz" },
|
||||||
|
{ "http://example.org/foo/bar/",
|
||||||
|
"http://example.org/foo/bar/" },
|
||||||
|
{ "http://example.org/foo//baz",
|
||||||
|
"http://example.org/foo//baz" },
|
||||||
|
{ "http://example.org/foo//",
|
||||||
|
"http://example.org/foo//" },
|
||||||
|
{ "http://example.org//bar/baz",
|
||||||
|
"http://example.org//bar/baz" },
|
||||||
|
{ "http://example.org//bar/",
|
||||||
|
"http://example.org//bar/" },
|
||||||
|
{ "http://example.org///baz",
|
||||||
|
"http://example.org///baz" },
|
||||||
|
{ "http://example.org///",
|
||||||
|
"http://example.org///" },
|
||||||
|
{ "http://example.org/foo/bar/baz/..",
|
||||||
|
"http://example.org/foo/bar/" },
|
||||||
|
{ "http://example.org/foo/bar//..",
|
||||||
|
"http://example.org/foo/bar/" },
|
||||||
|
{ "http://example.org/foo//baz/..",
|
||||||
|
"http://example.org/foo//" },
|
||||||
|
{ "http://example.org/foo///..",
|
||||||
|
"http://example.org/foo//" },
|
||||||
|
{ "http://example.org//bar/baz/..",
|
||||||
|
"http://example.org//bar/" },
|
||||||
|
{ "http://example.org//bar//..",
|
||||||
|
"http://example.org//bar/" },
|
||||||
|
{ "http://example.org///baz/..",
|
||||||
|
"http://example.org///" },
|
||||||
|
{ "http://example.org////..",
|
||||||
|
"http://example.org///" },
|
||||||
|
{ "http://example.org/foo/..//bar/baz",
|
||||||
|
"http://example.org//bar/baz" },
|
||||||
|
{ "http://example.org//.//foo",
|
||||||
|
"http://example.org///foo" },
|
||||||
|
{ "http://example.org//./../foo",
|
||||||
|
"http://example.org/foo" },
|
||||||
|
{ "http://example.org/gag///./../..",
|
||||||
|
"http://example.org/gag/" },
|
||||||
|
};
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof_array(tests); ++i)
|
||||||
|
test_1_normalize_uri(tests[i].orig, tests[i].norm);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
test_normalize_uri();
|
||||||
|
printf("Total %d failures, %d successes.\n", failures, successes);
|
||||||
|
return failures ? EXIT_FAILURE : 0;
|
||||||
|
}
|
@ -43,7 +43,11 @@
|
|||||||
static inline int
|
static inline int
|
||||||
end_of_dir(unsigned char c)
|
end_of_dir(unsigned char c)
|
||||||
{
|
{
|
||||||
return c == POST_CHAR || c == '#' || c == ';' || c == '?';
|
/* This used to check for c == ';' as well. But section 3.3
|
||||||
|
* of RFC 2396 explicitly says that parameters in a path
|
||||||
|
* segment "are not significant to the parsing of relative
|
||||||
|
* references." */
|
||||||
|
return c == POST_CHAR || c == '#' || c == '?';
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
@ -700,16 +704,14 @@ normalize_uri(struct uri *uri, unsigned char *uristring)
|
|||||||
if (uri->protocol != PROTOCOL_UNKNOWN)
|
if (uri->protocol != PROTOCOL_UNKNOWN)
|
||||||
need_slash = get_protocol_need_slash_after_host(uri->protocol);
|
need_slash = get_protocol_need_slash_after_host(uri->protocol);
|
||||||
|
|
||||||
/* We want to start at the first slash to also reduce URIs like
|
|
||||||
* http://host//index.html to http://host/index.html */
|
|
||||||
path = uri->data - need_slash;
|
path = uri->data - need_slash;
|
||||||
dest = src = path;
|
dest = src = path;
|
||||||
|
|
||||||
/* This loop mangles the URI string by removing directory elevators and
|
/* This loop mangles the URI string by removing ".." and "." segments.
|
||||||
* other cruft. Example: /.././etc////..//usr/ -> /usr/ */
|
* However it must not alter "//" without reason; see bug 744. */
|
||||||
while (*dest) {
|
while (*dest) {
|
||||||
/* If the following pieces are the LAST parts of URL, we remove
|
/* If the following pieces are the LAST parts of URL, we remove
|
||||||
* them as well. See RFC 1808 for details. */
|
* them as well. See RFC 2396 section 5.2 for details. */
|
||||||
|
|
||||||
if (end_of_dir(src[0])) {
|
if (end_of_dir(src[0])) {
|
||||||
/* URL data contains no more path. */
|
/* URL data contains no more path. */
|
||||||
@ -734,20 +736,25 @@ normalize_uri(struct uri *uri, unsigned char *uristring)
|
|||||||
|
|
||||||
} else if (src[2] == '.'
|
} else if (src[2] == '.'
|
||||||
&& (is_uri_dir_sep(uri, src[3]) || !src[3])) {
|
&& (is_uri_dir_sep(uri, src[3]) || !src[3])) {
|
||||||
/* /../ or /.. - skip it and preceding element. */
|
/* /../ or /.. - skip it and preceding element.
|
||||||
|
*
|
||||||
|
* <path> "/foo/bar" <dest> ...
|
||||||
|
* <src> ("/../" or "/..\0") ...
|
||||||
|
*
|
||||||
|
* Remove "bar" and the directory
|
||||||
|
* separator that precedes it. The
|
||||||
|
* separator will be added back in the
|
||||||
|
* next iteration unless another ".."
|
||||||
|
* follows, in which case it will be
|
||||||
|
* added later. "bar" may be empty. */
|
||||||
|
|
||||||
/* First back out the last incrementation of
|
|
||||||
* @dest (dest++) to get the position that was
|
|
||||||
* last asigned to. */
|
|
||||||
if (dest > path) dest--;
|
|
||||||
|
|
||||||
/* @dest might be pointing to a dir separator
|
|
||||||
* so we decrement before any testing. */
|
|
||||||
while (dest > path) {
|
while (dest > path) {
|
||||||
dest--;
|
dest--;
|
||||||
if (is_uri_dir_sep(uri, *dest)) break;
|
if (is_uri_dir_sep(uri, *dest)) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* <path> "/foo" <dest> "/bar" ...
|
||||||
|
* <src> ("/../" or "/..\0") ... */
|
||||||
if (!src[3]) {
|
if (!src[3]) {
|
||||||
/* /.. - add ending slash and stop */
|
/* /.. - add ending slash and stop */
|
||||||
*dest++ = *src;
|
*dest++ = *src;
|
||||||
@ -759,10 +766,6 @@ normalize_uri(struct uri *uri, unsigned char *uristring)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (is_uri_dir_sep(uri, src[1])) {
|
|
||||||
/* // - ignore first '/'. */
|
|
||||||
src += 1;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We don't want to access memory past the NUL char. */
|
/* We don't want to access memory past the NUL char. */
|
||||||
|
@ -575,6 +575,9 @@ has_nul_byte:
|
|||||||
unsigned char *param;
|
unsigned char *param;
|
||||||
int path_len, del_len, param_len;
|
int path_len, del_len, param_len;
|
||||||
|
|
||||||
|
/* TODO: Should this be changed to allow TERM_EXEC_NEWWIN
|
||||||
|
* in a blocked terminal? There is similar code in
|
||||||
|
* exec_on_terminal(). --KON, 2007 */
|
||||||
if (is_blocked() && fg != TERM_EXEC_BG) {
|
if (is_blocked() && fg != TERM_EXEC_BG) {
|
||||||
if (*delete.source) unlink(delete.source);
|
if (*delete.source) unlink(delete.source);
|
||||||
goto nasty_thing;
|
goto nasty_thing;
|
||||||
|
@ -288,6 +288,9 @@ exec_on_terminal(struct terminal *term, unsigned char *path,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: Should this be changed to allow TERM_EXEC_NEWWIN
|
||||||
|
* in a blocked terminal? There is similar code in
|
||||||
|
* in_sock(). --KON, 2007 */
|
||||||
if (fg != TERM_EXEC_BG && is_blocked()) {
|
if (fg != TERM_EXEC_BG && is_blocked()) {
|
||||||
unlink(delete);
|
unlink(delete);
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user