mirror of
https://github.com/rkd77/elinks.git
synced 2024-12-04 14:46:47 -05:00
Merge branch 'elinks-0.12' into elinks-0.13
Conflicts: src/document/document.h src/encoding/encoding.c src/network/connection.c src/protocol/bittorrent/bittorrent.c src/protocol/bittorrent/bittorrent.h src/protocol/bittorrent/common.h src/protocol/bittorrent/connection.c src/protocol/bittorrent/dialogs.c src/protocol/bittorrent/tracker.c src/protocol/file/cgi.c src/protocol/http/http.c
This commit is contained in:
commit
a73fe73cd2
22
NEWS
22
NEWS
@ -54,13 +54,14 @@ have already been considered.
|
||||
|
||||
* Fixed bugs that were not in previous versions:
|
||||
- critical bug 1009: assertion failure in add_snippets()
|
||||
(mostly reverted)
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
ELinks 0.12pre1.GIT now:
|
||||
------------------------
|
||||
|
||||
To be released as 0.12pre2, 0.12rc1, or even 0.12.0. This branch
|
||||
generally also includes the bug fixes made in ELinks 0.11.4.GIT.
|
||||
To be released as 0.12pre2, 0.12rc1, or even 0.12.0. This branch also
|
||||
includes the changes listed under "ELinks 0.11.4.GIT now" below.
|
||||
|
||||
* bug 954, enhancement 952: Keep track of ECMAScript form and input
|
||||
objects instead of constructing new ones on every access. When the
|
||||
@ -72,15 +73,24 @@ generally also includes the bug fixes made in ELinks 0.11.4.GIT.
|
||||
JS_CallFunction, which can crash if given a closure.
|
||||
* critical bug 1031: Use the same JSRuntime for both user SMJS and
|
||||
scripts on web pages, to work around SpiderMonkey bug 378918.
|
||||
* bug 698: Attach controls to the intended form even if it is
|
||||
incorrectly nested in a table. (Was broken in 0.11.4.)
|
||||
* bug 1013: Don't assume errno values are between 0 and 100000.
|
||||
* bug 1022: Add connection.ssl.trusted_ca_file setting for GnuTLS.
|
||||
Before this, ELinks did not trust any certificate authorities when
|
||||
it used GnuTLS, so certificate verification always failed if you
|
||||
enabled it at connection.ssl.cert_verify.
|
||||
* bug 1040: Blacklist servers that don't support TLS. This reduces
|
||||
SSL errors especially in HTTP POST requests using GnuTLS.
|
||||
* minor bug 951: SpiderMonkey scripting objects used to prevent ELinks
|
||||
from removing files from the memory cache
|
||||
from removing files from the memory cache.
|
||||
|
||||
Bugs that should be removed from NEWS before the 0.12.0 release:
|
||||
|
||||
* critical: Fix crash after a tab was opened during reload. This was
|
||||
triggered by the bug 620 fix in ELinks 0.12pre1.
|
||||
* critical bug 1018: Avoid an assertion failure when selecting a value
|
||||
from a pop-up menu for an input field in a tab that is no longer
|
||||
current, e.g. because another tab was opened with elinks -remote.
|
||||
This bug was first released in ELinks 0.12pre1.
|
||||
* major bug 1026 in user SMJS: Protect the callback of elinks.load_uri
|
||||
from the garbage collector. The elinks.load_uri method was added in
|
||||
ELinks 0.12pre1.
|
||||
@ -262,6 +272,8 @@ To be released as 0.11.5.
|
||||
* critical bug 1030: an assertion used to fail in the search dialog
|
||||
on systems that lack a usable <regex.h>
|
||||
* major bug 503: various fixes in parsing and updating of elinks.conf
|
||||
* bug 698: Attach controls to the intended form even if it is
|
||||
incorrectly nested in a table. (Was broken in 0.11.4.)
|
||||
* build bug 1021: fixed uninitialized variable in http_got_header
|
||||
|
||||
ELinks 0.11.4:
|
||||
|
@ -191,7 +191,7 @@ AC_CHECK_HEADERS(fcntl.h limits.h time.h unistd.h)
|
||||
AC_CHECK_HEADERS(sigaction.h)
|
||||
AC_CHECK_HEADERS(arpa/inet.h)
|
||||
AC_CHECK_HEADERS(netinet/in_systm.h netinet/in_system.h netinet/ip.h)
|
||||
AC_CHECK_HEADERS(net/if.h netdb.h netinet/in.h netinet/in6_var.h)
|
||||
AC_CHECK_HEADERS(netdb.h netinet/in.h netinet/in6_var.h)
|
||||
AC_CHECK_HEADERS(ifaddrs.h)
|
||||
AC_CHECK_HEADERS(sys/cygwin.h io.h)
|
||||
AC_CHECK_HEADERS(sys/fmutex.h)
|
||||
@ -202,6 +202,11 @@ AC_CHECK_HEADERS(sys/signal.h)
|
||||
AC_CHECK_HEADERS(sys/socket.h)
|
||||
AC_CHECK_HEADERS(sys/time.h)
|
||||
AC_CHECK_HEADERS(sys/utsname.h)
|
||||
AC_CHECK_HEADERS([net/if.h], [], [],
|
||||
[[#ifdef HAVE_SYS_SOCKET_H
|
||||
# include <sys/socket.h> /* <net/if.h> on Mac OS X 10.5.4 needs this */
|
||||
#endif
|
||||
]])
|
||||
AC_CHECK_HEADERS(stdint.h inttypes.h)
|
||||
AC_CHECK_HEADERS(locale.h pwd.h)
|
||||
AC_CHECK_HEADERS(termios.h)
|
||||
|
@ -14,7 +14,9 @@ PDF_DIR = $(DESTDIR)$(docdir)/$(PACKAGE)/pdf
|
||||
TXT_DIR = $(DESTDIR)$(docdir)/$(PACKAGE)/txt
|
||||
|
||||
ASCIIDOC_CONF = $(srcdir)asciidoc.conf
|
||||
ASCIIDOC_FLAGS += -f $(ASCIIDOC_CONF) \
|
||||
ASCIIDOC_FLAGS += --no-conf -f $(srcdir)tools/asciidoc/asciidoc.conf \
|
||||
-f $(srcdir)tools/asciidoc/$(call backend).conf \
|
||||
-f $(ASCIIDOC_CONF) \
|
||||
-a "builddir=$(CURDIR)/" \
|
||||
-a asciidoc7compatible \
|
||||
-a elinks_version=$(VERSION)
|
||||
|
18
doc/tools/asciidoc/COPYRIGHT
Normal file
18
doc/tools/asciidoc/COPYRIGHT
Normal file
@ -0,0 +1,18 @@
|
||||
Copyright (C) 2000 Stuart Rackham
|
||||
|
||||
Email: srackham@methods.co.nz
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or (at
|
||||
your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
USA.
|
14
doc/tools/asciidoc/README
Normal file
14
doc/tools/asciidoc/README
Normal file
@ -0,0 +1,14 @@
|
||||
The files in this directory, except this README itself,
|
||||
have been copied from the AsciiDoc 7.1.2 source package.
|
||||
|
||||
In the past, we have hit annoying incompatibilities when
|
||||
people have attempted to rebuild ELinks documentation
|
||||
with new versions of AsciiDoc:
|
||||
|
||||
http://bugzilla.elinks.cz/show_bug.cgi?id=989
|
||||
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=491820
|
||||
|
||||
So now we bundle the configuration files from a known good version
|
||||
to let ELinks documentation be built with them regardless of which
|
||||
version has been installed on the machine. This should keep things
|
||||
working as long as the configuration file format remains compatible.
|
335
doc/tools/asciidoc/asciidoc.conf
Normal file
335
doc/tools/asciidoc/asciidoc.conf
Normal file
@ -0,0 +1,335 @@
|
||||
#
|
||||
# asciidoc.conf
|
||||
#
|
||||
# Asciidoc global configuration file.
|
||||
# Contains backend independent configuration settings that are applied to all
|
||||
# AsciiDoc documents.
|
||||
#
|
||||
|
||||
[miscellaneous]
|
||||
tabsize=8
|
||||
textwidth=70
|
||||
newline=\r\n
|
||||
|
||||
[attributes]
|
||||
iconsdir=./images/icons
|
||||
encoding=UTF-8
|
||||
quirks=
|
||||
empty=
|
||||
amp=&
|
||||
lt=<
|
||||
gt=>
|
||||
brvbar=|
|
||||
nbsp= 
|
||||
backslash=\
|
||||
# Attribute and AttributeList element patterns.
|
||||
attributeentry-pattern=^:(?P<attrname>[a-zA-Z].*?):(?P<attrvalue>.*)$
|
||||
attributelist-pattern=(?u)(^\[\[(?P<id>[\w\-_]+)\]\]$)|(^\[(?P<attrlist>.*)\]$)
|
||||
|
||||
[titles]
|
||||
subs=specialcharacters,quotes,replacements,macros,attributes
|
||||
# Double-line title pattern and underlines.
|
||||
sectiontitle=^(?P<title>.*?)$
|
||||
underlines="==","--","~~","^^","++"
|
||||
# Single-line title patterns.
|
||||
sect0=^= (?P<title>[\S].*)$
|
||||
sect1=^== (?P<title>[\S].*)$
|
||||
sect2=^=== (?P<title>[\S].*)$
|
||||
sect3=^==== (?P<title>[\S].*)$
|
||||
sect4=^===== (?P<title>[\S].*)$
|
||||
blocktitle=^\.(?P<title>\S.*)$
|
||||
|
||||
[specialcharacters]
|
||||
&=&
|
||||
<=<
|
||||
>=>
|
||||
|
||||
[quotes]
|
||||
# Don't use "double-quote" characters -- they interfere with quoted element
|
||||
# attribute values (see ``alternative'' below).
|
||||
*=strong
|
||||
'=emphasis
|
||||
`=monospaced
|
||||
``|''=quoted
|
||||
\##|##=unquoted
|
||||
|
||||
[specialwords]
|
||||
emphasizedwords=
|
||||
strongwords=
|
||||
monospacedwords=
|
||||
|
||||
[tags]
|
||||
# $$ inline passthrough.
|
||||
passthrough=|
|
||||
|
||||
[replacements]
|
||||
# Replacements performed in order of configuration file entry. The first entry
|
||||
# of each replacement pair performs the (non-escaped) replacement, the second
|
||||
# strips the backslash from the esaped replacement.
|
||||
|
||||
# (C) Copyright (entity reference ©)
|
||||
(?<!\\)\(C\)=©
|
||||
\\\(C\)=(C)
|
||||
|
||||
# (R) registered trade mark (entity reference ®
|
||||
(?<!\\)\(R\)=®
|
||||
\\\(R\)=(R)
|
||||
|
||||
# (TM) Trademark (entity reference ™)
|
||||
(?<!\\)\(TM\)=™
|
||||
\\\(TM\)=(TM)
|
||||
|
||||
# -- Spaced and unspaced em dashes (entity reference —)
|
||||
# But disallow unspaced in man pages because double-dash option name prefixes
|
||||
# are pervasive.
|
||||
ifndef::doctype-manpage[]
|
||||
(^|[^-\\])--($|[^-])=\1—\2
|
||||
endif::doctype-manpage[]
|
||||
ifdef::doctype-manpage[]
|
||||
(^|\s*[^\S\\])--($|\s+)=\1—\2
|
||||
endif::doctype-manpage[]
|
||||
\\--(?!-)=--
|
||||
|
||||
# ... Ellipsis (entity reference …)
|
||||
(?<!\\)\.\.\.=…
|
||||
\\\.\.\.=...
|
||||
|
||||
##
|
||||
# The following require non-standard embedded fonts in PDF files so are not
|
||||
# enabled.
|
||||
# -> right arrow
|
||||
#->=→
|
||||
# => right double arrow
|
||||
#=>=⇒
|
||||
# <- left arrow
|
||||
#<-=←
|
||||
# <= left double arrow
|
||||
#<\==⇐
|
||||
|
||||
# Paragraphs.
|
||||
[paradef-default]
|
||||
delimiter=(?s)(?P<text>\S.*)
|
||||
template=paragraph
|
||||
posattrs=style
|
||||
verse-style=template="verseparagraph"
|
||||
NOTE-style=template="admonitionparagraph",name="note",caption="Note"
|
||||
TIP-style=template="admonitionparagraph",name="tip",caption="Tip"
|
||||
IMPORTANT-style=template="admonitionparagraph",name="important",caption="Important"
|
||||
WARNING-style=template="admonitionparagraph",name="warning",caption="Warning"
|
||||
CAUTION-style=template="admonitionparagraph",name="caution",caption="Caution"
|
||||
|
||||
[paradef-literal]
|
||||
delimiter=(?s)(?P<text>\s+.*)
|
||||
options=listelement
|
||||
template=literalparagraph
|
||||
subs=verbatim
|
||||
|
||||
[paradef-admonition]
|
||||
delimiter=(?s)^\s*(?P<style>NOTE|TIP|IMPORTANT|WARNING|CAUTION):\s+(?P<text>.+)
|
||||
NOTE-style=template="admonitionparagraph",name="note",caption="Note"
|
||||
TIP-style=template="admonitionparagraph",name="tip",caption="Tip"
|
||||
IMPORTANT-style=template="admonitionparagraph",name="important",caption="Important"
|
||||
WARNING-style=template="admonitionparagraph",name="warning",caption="Warning"
|
||||
CAUTION-style=template="admonitionparagraph",name="caution",caption="Caution"
|
||||
|
||||
[macros]
|
||||
# Inline macros.
|
||||
# Backslash prefix required for escape processing.
|
||||
# (?s) re flag for line spanning.
|
||||
(?su)[\\]?(?P<name>\w(\w|-)*?):(?P<target>\S*?)(\[(?P<attrlist>.*?)\])=
|
||||
# Anchor: [[[id]]]. Bibliographic anchor.
|
||||
(?su)[\\]?\[\[\[(?P<attrlist>[\w][\w-]*?)\]\]\]=anchor3
|
||||
# Anchor: [[id,xreflabel]]
|
||||
(?su)[\\]?\[\[(?P<attrlist>[\w"].*?)\]\]=anchor2
|
||||
# Link: <<id,text>>
|
||||
(?su)[\\]?<<(?P<attrlist>[\w"].*?)>>=xref2
|
||||
# Index term: ++primary,secondar,tertiary++
|
||||
#(?su)(?<!\S)[\\]?\+\+(?P<attrlist>.+?)\+\+(?!\+)=indexterm
|
||||
(?su)(?<!\S)[\\]?\+\+(?P<attrlist>[^+].*?)\+\+(?!\+)=indexterm
|
||||
# Index term: +primary+
|
||||
# Follows ++...++ macro otherwise it will match them.
|
||||
#(?<!\S)[\\]?\+(?P<attrlist>[^\s\+].*?)\+(?!\+)=indexterm2
|
||||
(?<!\S)[\\]?\+(?P<attrlist>[^\s\+][^+].*?)\+(?!\+)=indexterm2
|
||||
# Callout
|
||||
[\\]?<(?P<index>\d+)>=callout
|
||||
|
||||
# Block macros.
|
||||
(?u)^(?P<name>\w(\w|-)*?)::(?P<target>\S*?)(\[(?P<attrlist>.*?)\])$=#
|
||||
^'{4,}$=#ruler
|
||||
^//([^/].*|)$=#comment
|
||||
|
||||
# System macros.
|
||||
# The default macro which is hardwired into asciidoc.
|
||||
#(?u)^(?P<name>\w(\w|-)*?)::(?P<target>\S*?)(\[(?P<attrlist>.*?)\])$=+
|
||||
|
||||
# Delimited blocks.
|
||||
[blockdef-comment]
|
||||
delimiter=^/{4,}
|
||||
options=skip
|
||||
|
||||
[comment-blockmacro]
|
||||
# Outputs nothing.
|
||||
|
||||
[blockdef-sidebar]
|
||||
delimiter=^\*{4,}$
|
||||
template=sidebarblock
|
||||
options=sectionbody
|
||||
|
||||
[blockdef-list]
|
||||
delimiter=^--$
|
||||
template=listblock
|
||||
options=list
|
||||
|
||||
[listblock]
|
||||
|
|
||||
|
||||
[blockdef-passthrough]
|
||||
delimiter=^\+{4,}$
|
||||
template=passthroughblock
|
||||
subs=attributes,macros
|
||||
|
||||
[blockdef-listing]
|
||||
delimiter=^-{4,}$
|
||||
template=listingblock
|
||||
subs=verbatim
|
||||
|
||||
[blockdef-literal]
|
||||
delimiter=^\.{4,}$
|
||||
template=literalblock
|
||||
subs=verbatim
|
||||
posattrs=style
|
||||
verse-style=template="verseblock",subs="normal"
|
||||
|
||||
[blockdef-quote]
|
||||
delimiter=^_{4,}$
|
||||
template=quoteblock
|
||||
options=sectionbody
|
||||
subs=normal
|
||||
posattrs=attribution,citetitle
|
||||
|
||||
[blockdef-example]
|
||||
delimiter=^\={4,}$
|
||||
template=exampleblock
|
||||
options=sectionbody
|
||||
posattrs=style
|
||||
NOTE-style=template="admonitionblock",name="note",caption="Note"
|
||||
TIP-style=template="admonitionblock",name="tip",caption="Tip"
|
||||
IMPORTANT-style=template="admonitionblock",name="important",caption="Important"
|
||||
WARNING-style=template="admonitionblock",name="warning",caption="Warning"
|
||||
CAUTION-style=template="admonitionblock",name="caution",caption="Caution"
|
||||
|
||||
|
||||
# Lists.
|
||||
[listdef-bulleted]
|
||||
type=bulleted
|
||||
delimiter=^\s*- +(?P<text>.+)$
|
||||
listtag=ilist
|
||||
itemtag=ilistitem
|
||||
texttag=ilisttext
|
||||
|
||||
[listdef-bulleted2]
|
||||
type=bulleted
|
||||
delimiter=^\s*\* +(?P<text>.+)$
|
||||
listtag=ilist
|
||||
itemtag=ilistitem
|
||||
texttag=ilisttext
|
||||
|
||||
[listdef-numbered]
|
||||
type=numbered
|
||||
delimiter=^\s*(?P<index>\d*)\. +(?P<text>.+)$
|
||||
listtag=olist
|
||||
itemtag=olistitem
|
||||
texttag=olisttext
|
||||
|
||||
[listdef-numbered2]
|
||||
type=numbered
|
||||
delimiter=^\s*(?P<index>[.a-z])\. +(?P<text>.+)$
|
||||
listtag=olist2
|
||||
itemtag=olistitem
|
||||
texttag=olisttext
|
||||
|
||||
[listdef-vlabeled]
|
||||
type=labeled
|
||||
delimiter=^\s*(?P<label>[\S].*)::$
|
||||
listtag=vlist
|
||||
itemtag=vlistitem
|
||||
texttag=vlisttext
|
||||
entrytag=vlistentry
|
||||
labeltag=vlistterm
|
||||
|
||||
[listdef-vlabeled2]
|
||||
type=labeled
|
||||
delimiter=^\s*(?P<label>[\S].*);;$
|
||||
listtag=vlist
|
||||
itemtag=vlistitem
|
||||
texttag=vlisttext
|
||||
entrytag=vlistentry
|
||||
labeltag=vlistterm
|
||||
|
||||
[listdef-hlabeled]
|
||||
type=labeled
|
||||
delimiter=^\s*(?P<label>[\S].*)::\s+(?P<text>.+)$
|
||||
listtag=hlist
|
||||
itemtag=hlistitem
|
||||
texttag=hlisttext
|
||||
entrytag=hlistentry
|
||||
labeltag=hlistterm
|
||||
|
||||
[listdef-hlabeled2]
|
||||
type=labeled
|
||||
delimiter=^\s*(?P<label>[\S].*);;\s+(?P<text>.+)$
|
||||
listtag=hlist
|
||||
itemtag=hlistitem
|
||||
texttag=hlisttext
|
||||
entrytag=hlistentry
|
||||
labeltag=hlistterm
|
||||
|
||||
|
||||
# Question and Answer list.
|
||||
[listdef-qanda]
|
||||
type=labeled
|
||||
delimiter=^\s*(?P<label>[\S].*)\?\?$
|
||||
listtag=qlist
|
||||
itemtag=qlistitem
|
||||
texttag=qlisttext
|
||||
entrytag=qlistentry
|
||||
labeltag=qlistterm
|
||||
|
||||
# Bibliography list.
|
||||
[listdef-bibliography]
|
||||
type=bulleted
|
||||
delimiter=^\+ +(?P<text>.+)$
|
||||
listtag=blist
|
||||
itemtag=blistitem
|
||||
texttag=blisttext
|
||||
|
||||
# Glossary list.
|
||||
[listdef-glossary]
|
||||
type=labeled
|
||||
delimiter=^(?P<label>[\S].*):-$
|
||||
listtag=glist
|
||||
itemtag=glistitem
|
||||
texttag=glisttext
|
||||
entrytag=glistentry
|
||||
labeltag=glistterm
|
||||
|
||||
# Callout list.
|
||||
[listdef-callout]
|
||||
type=callout
|
||||
delimiter=^<?(?P<index>\d*)> +(?P<text>.+)$
|
||||
listtag=colist
|
||||
itemtag=colistitem
|
||||
texttag=colisttext
|
||||
|
||||
# Tables.
|
||||
[tabledef-default]
|
||||
fillchar=-
|
||||
format=fixed
|
||||
|
||||
[tabledef-csv]
|
||||
fillchar=~
|
||||
format=csv
|
||||
|
||||
[tabledef-dsv]
|
||||
fillchar=_
|
||||
format=dsv
|
589
doc/tools/asciidoc/docbook.conf
Normal file
589
doc/tools/asciidoc/docbook.conf
Normal file
@ -0,0 +1,589 @@
|
||||
#
|
||||
# docbook.conf
|
||||
#
|
||||
# Asciidoc configuration file.
|
||||
# Default docbook backend.
|
||||
#
|
||||
|
||||
[miscellaneous]
|
||||
outfilesuffix=.xml
|
||||
# Printable page width in pts.
|
||||
pagewidth=380
|
||||
pageunits=pt
|
||||
|
||||
[attributes]
|
||||
basebackend=docbook
|
||||
basebackend-docbook=
|
||||
|
||||
[replacements]
|
||||
# Line break markup is dropped (there is no DocBook line break tag).
|
||||
(?m)^(.*)\s\+$=\1
|
||||
# Superscripts.
|
||||
\^(.+?)\^=<superscript>\1</superscript>
|
||||
# Subscripts.
|
||||
~(.+?)~=<subscript>\1</subscript>
|
||||
|
||||
[ruler-blockmacro]
|
||||
# Only applies to HTML so don't output anything.
|
||||
|
||||
[image-inlinemacro]
|
||||
<inlinemediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="{target}"{width? contentwidth="{width}pt"}{height? contentdepth="{height}pt"}/>
|
||||
</imageobject>
|
||||
<textobject><phrase>{1={target}}</phrase></textobject>
|
||||
</inlinemediaobject>
|
||||
|
||||
[image-blockmacro]
|
||||
<figure{id? id="{id}"}><title>{title}</title>
|
||||
{title%}<informalfigure{id? id="{id}"}>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="{target}"{width? contentwidth="{width}pt"}{height? contentdepth="{height}pt"}/>
|
||||
</imageobject>
|
||||
<textobject><phrase>{1={target}}</phrase></textobject>
|
||||
</mediaobject>
|
||||
{title#}</figure>
|
||||
{title%}</informalfigure>
|
||||
|
||||
[indexterm-inlinemacro]
|
||||
# Inline index term.
|
||||
# Generate separate index entries for primary, secondary and tertiary
|
||||
# descriptions.
|
||||
# Primary only.
|
||||
{2%}<indexterm>
|
||||
{2%} <primary>{1}</primary>
|
||||
{2%}</indexterm>
|
||||
# Primary and secondary.
|
||||
{2#}{3%}<indexterm>
|
||||
{2#}{3%} <primary>{1}</primary><secondary>{2}</secondary>
|
||||
{2#}{3%}</indexterm>
|
||||
{2#}{3%}<indexterm>
|
||||
{2#}{3%} <primary>{2}</primary>
|
||||
{2#}{3%}</indexterm>
|
||||
# Primary, secondary and tertiary.
|
||||
{3#}<indexterm>
|
||||
<primary>{1}</primary><secondary>{2}</secondary><tertiary>{3}</tertiary>
|
||||
{3#}</indexterm>
|
||||
{3#}<indexterm>
|
||||
<primary>{2}</primary><secondary>{3}</secondary>
|
||||
{3#}</indexterm>
|
||||
{3#}<indexterm>
|
||||
<primary>{3}</primary>
|
||||
{3#}</indexterm>
|
||||
|
||||
[indexterm2-inlinemacro]
|
||||
# Inline index term.
|
||||
# Single entry index term that is visible in the primary text flow.
|
||||
<indexterm>
|
||||
<primary>{1}</primary>
|
||||
</indexterm>
|
||||
{1}
|
||||
|
||||
[footnote-inlinemacro]
|
||||
# Inline footnote.
|
||||
<footnote><simpara>{0}</simpara></footnote>
|
||||
|
||||
[callout-inlinemacro]
|
||||
# Inline callout.
|
||||
<co id="{coid}"/>
|
||||
|
||||
[tags]
|
||||
# Bulleted, numbered and labeled list tags.
|
||||
ilist=<itemizedlist{id? id="{id}"}>{title?<title>{title}</title>}|</itemizedlist>
|
||||
ilistitem=<listitem>|</listitem>
|
||||
ilisttext=<simpara>|</simpara>
|
||||
olist=<orderedlist{id? id="{id}"}>{title?<title>{title}</title>}|</orderedlist>
|
||||
olist2=<orderedlist{id? id="{id}"} numeration="loweralpha">|</orderedlist>
|
||||
olistitem=<listitem>|</listitem>
|
||||
olisttext=<simpara>|</simpara>
|
||||
vlist=<variablelist{id? id="{id}"}>{title?<title>{title}</title>}|</variablelist>
|
||||
vlistentry=<varlistentry>|</varlistentry>
|
||||
vlistterm=<term>|</term>
|
||||
vlisttext=<simpara>|</simpara>
|
||||
vlistitem=<listitem>|</listitem>
|
||||
# Horizontal labeled list (implemented with two column table).
|
||||
# Hardwired column widths to 30%,70% because the current crop of PDF
|
||||
# generators do not auto calculate column widths.
|
||||
hlist=<{title?table}{title!informaltable}{id? id="{id}"} tabstyle="{style=hlabeledlist}" pgwide="0" frame="none" colsep="0" rowsep="0">{title?<title>{title}</title>}<tgroup cols="2"><colspec colwidth="{1=3}*"/><colspec colwidth="{2=7}*"/><tbody valign="top">|</tbody></tgroup><{title?/table}{title!/informaltable}>
|
||||
hlistentry=<row>|</row>
|
||||
hlisttext=<simpara>|</simpara>
|
||||
hlistterm=<entry><simpara>|</simpara></entry>
|
||||
hlistitem=<entry>|</entry>
|
||||
|
||||
# Question and Answer list.
|
||||
qlist=<qandaset{id? id="{id}"}>{title?<title>{title}</title>}|</qandaset>
|
||||
qlistentry=<qandaentry>|</qandaentry>
|
||||
qlistterm=<question><simpara>|</simpara></question>
|
||||
qlistitem=<answer>|</answer>
|
||||
qlisttext=<simpara>|</simpara>
|
||||
# Bibliography list.
|
||||
blist=|
|
||||
blistitem=<bibliomixed>|</bibliomixed>
|
||||
blisttext=<bibliomisc>|</bibliomisc>
|
||||
# Glossary list.
|
||||
glist=|
|
||||
glistentry=<glossentry>|</glossentry>
|
||||
glistterm=<glossterm>|</glossterm>
|
||||
glistitem=<glossdef>|</glossdef>
|
||||
glisttext=<simpara>|</simpara>
|
||||
# Callout list.
|
||||
colist=<calloutlist{id? id="{id}"}>{title?<title>{title}</title>}|</calloutlist>
|
||||
colistitem=<callout arearefs="{coids}">|</callout>
|
||||
colisttext=<simpara>|</simpara>
|
||||
|
||||
# Quoted text
|
||||
emphasis=<emphasis>|</emphasis>
|
||||
strong=<emphasis role="strong">|</emphasis>
|
||||
monospaced=<literal>|</literal>
|
||||
quoted={amp}#8220;|{amp}#8221;
|
||||
unquoted=|
|
||||
|
||||
# $$ inline passthrough.
|
||||
passthrough=|
|
||||
|
||||
# Inline macros
|
||||
[http-inlinemacro]
|
||||
<ulink url="{name}:{target}">{0={name}:{target}}</ulink>
|
||||
[https-inlinemacro]
|
||||
<ulink url="{name}:{target}">{0={name}:{target}}</ulink>
|
||||
[ftp-inlinemacro]
|
||||
<ulink url="{name}:{target}">{0={name}:{target}}</ulink>
|
||||
[file-inlinemacro]
|
||||
<ulink url="{name}:{target}">{0={name}:{target}}</ulink>
|
||||
[mailto-inlinemacro]
|
||||
<ulink url="{name}:{target}">{0={target}}</ulink>
|
||||
#<email>{target}</email>
|
||||
[link-inlinemacro]
|
||||
<ulink url="{target}">{0={target}}</ulink>
|
||||
# anchor:id[text]
|
||||
[anchor-inlinemacro]
|
||||
<anchor id="{target}" xreflabel="{0=[{target}]}"/>
|
||||
# [[id,text]]
|
||||
[anchor2-inlinemacro]
|
||||
<anchor id="{1}" xreflabel="{2=[{1}]}"/>
|
||||
# [[[id]]]
|
||||
[anchor3-inlinemacro]
|
||||
<anchor id="{1}" xreflabel="[{1}]"/>[{1}]
|
||||
# xref:id[text]
|
||||
[xref-inlinemacro]
|
||||
<link linkend="{target}">{0}</link>
|
||||
{2%}<xref linkend="{target}"/>
|
||||
# <<id,text>>
|
||||
[xref2-inlinemacro]
|
||||
<link linkend="{1}">{2}</link>
|
||||
{2%}<xref linkend="{1}"/>
|
||||
|
||||
|
||||
# Special word macros
|
||||
[emphasizedwords]
|
||||
<emphasis>{words}</emphasis>
|
||||
[monospacedwords]
|
||||
<literal>{words}</literal>
|
||||
[strongwords]
|
||||
<emphasis role="strong">{words}</emphasis>
|
||||
|
||||
# Paragraph substitution.
|
||||
[paragraph]
|
||||
<formalpara{id? id="{id}"}><title>{title}</title><para>
|
||||
{title%}<simpara{id? id="{id}"}>
|
||||
|
|
||||
{title%}</simpara>
|
||||
{title#}</para></formalpara>
|
||||
{empty}
|
||||
|
||||
[admonitionparagraph]
|
||||
<{name}{id? id="{id}"}><simpara>|</simpara></{name}>
|
||||
|
||||
[literalparagraph]
|
||||
# The literal block employs the same markup.
|
||||
template::[literalblock]
|
||||
|
||||
[verseparagraph]
|
||||
template::[verseblock]
|
||||
|
||||
# Delimited blocks.
|
||||
[literalblock]
|
||||
<example><title>{title}</title>
|
||||
<literallayout{id? id="{id}"} class="{font=monospaced}">
|
||||
|
|
||||
</literallayout>
|
||||
{title#}</example>
|
||||
|
||||
[listingblock]
|
||||
<example><title>{title}</title>
|
||||
<screen>
|
||||
|
|
||||
</screen>
|
||||
{title#}</example>
|
||||
|
||||
[verseblock]
|
||||
<formalpara{id? id="{id}"}><title>{title}</title><para>
|
||||
{title%}<literallayout{id? id="{id}"}>
|
||||
{title#}<literallayout>
|
||||
|
|
||||
</literallayout>
|
||||
{title#}</para></formalpara>
|
||||
|
||||
[sidebarblock]
|
||||
<sidebar{id? id="{id}"}>
|
||||
<title>{title}</title>
|
||||
|
|
||||
</sidebar>
|
||||
|
||||
[passthroughblock]
|
||||
|
|
||||
|
||||
[quoteblock]
|
||||
# The epigraph element may be more appropriate than blockquote.
|
||||
<blockquote{id? id="{id}"}>
|
||||
<title>{title}</title>
|
||||
<attribution>
|
||||
{attribution}
|
||||
<citetitle>{citetitle}</citetitle>
|
||||
</attribution>
|
||||
|
|
||||
</blockquote>
|
||||
|
||||
[exampleblock]
|
||||
<{title?example}{title!informalexample}{id? id="{id}"}>
|
||||
<title>{title}</title>
|
||||
|
|
||||
</{title?example}{title!informalexample}>
|
||||
|
||||
[admonitionblock]
|
||||
<{name}{id? id="{id}"}>
|
||||
<title>{title}</title>
|
||||
|
|
||||
</{name}>
|
||||
|
||||
# Tables.
|
||||
[tabledef-default]
|
||||
template=table
|
||||
colspec=<colspec colwidth="{colwidth}{pageunits}" align="{colalign}"/>
|
||||
bodyrow=<row>|</row>
|
||||
bodydata=<entry>|</entry>
|
||||
|
||||
[table]
|
||||
<{title?table}{title!informaltable}{id? id="{id}"} pgwide="0"
|
||||
frame="{frame=topbot}"
|
||||
{grid%rowsep="0" colsep="0"}
|
||||
rowsep="{grid@none|cols:0:1}" colsep="{grid@none|rows:0:1}"
|
||||
>
|
||||
<title>{title}</title>
|
||||
<tgroup cols="{cols}">
|
||||
{colspecs}
|
||||
{headrows#}<thead>
|
||||
{headrows}
|
||||
{headrows#}</thead>
|
||||
{footrows#}<tfoot>
|
||||
{footrows}
|
||||
{footrows#}</tfoot>
|
||||
<tbody>
|
||||
{bodyrows}
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</{title?table}{title!informaltable}>
|
||||
|
||||
[specialsections]
|
||||
ifdef::doctype-article[]
|
||||
^Abstract$=sect-abstract
|
||||
endif::doctype-article[]
|
||||
|
||||
ifdef::doctype-book[]
|
||||
^Colophon$=sect-colophon
|
||||
^Dedication$=sect-dedication
|
||||
^Preface$=sect-preface
|
||||
endif::doctype-book[]
|
||||
|
||||
^Index$=sect-index
|
||||
^(Bibliography|References)$=sect-bibliography
|
||||
^Glossary$=sect-glossary
|
||||
^Appendix [A-Z][:.](?P<title>.*)$=sect-appendix
|
||||
|
||||
# Special sections.
|
||||
[sect-preface]
|
||||
<preface{id? id="{id}"}>
|
||||
<title>{title}</title>
|
||||
|
|
||||
</preface>
|
||||
|
||||
[sect-index]
|
||||
<index{id? id="{id}"}>
|
||||
<title>{title}</title>
|
||||
|
|
||||
</index>
|
||||
|
||||
[sect-bibliography]
|
||||
<bibliography{id? id="{id}"}>
|
||||
<title>{title}</title>
|
||||
|
|
||||
</bibliography>
|
||||
|
||||
[sect-glossary]
|
||||
<glossary{id? id="{id}"}>
|
||||
<title>{title}</title>
|
||||
|
|
||||
</glossary>
|
||||
|
||||
[sect-appendix]
|
||||
<appendix{id? id="{id}"}>
|
||||
<title>{title}</title>
|
||||
|
|
||||
</appendix>
|
||||
|
||||
|
||||
[header-declarations]
|
||||
<?xml version="1.0" encoding="{encoding}"?>
|
||||
<!DOCTYPE {doctype-article?article}{doctype-book?book}{doctype-manpage?refentry} PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
|
||||
#-------------------------
|
||||
# article document type
|
||||
#-------------------------
|
||||
ifdef::doctype-article[]
|
||||
|
||||
[header]
|
||||
template::[header-declarations]
|
||||
|
||||
<article lang="en">
|
||||
{doctitle#}<articleinfo>
|
||||
<title>{doctitle}</title>
|
||||
<date>{date}</date>
|
||||
{authored#}<author>
|
||||
<firstname>{firstname}</firstname>
|
||||
<othername>{middlename}</othername>
|
||||
<surname>{lastname}</surname>
|
||||
<affiliation><address><email>{email}</email></address></affiliation>
|
||||
{authored#}</author>
|
||||
<authorinitials>{authorinitials}</authorinitials>
|
||||
|
||||
# If file named like source document with -revhistory.xml suffix exists
|
||||
# include it as the document history, otherwise use current revision.
|
||||
{revisionhistory#}{include:{docdir}/{docname}-revhistory.xml}
|
||||
{revisionhistory%}<revhistory><revision><revnumber>{revision}</revnumber><date>{date}</date>{authorinitials?<authorinitials>{authorinitials}</authorinitials>}{revremark?<revremark>{revremark}</revremark>}</revision></revhistory>
|
||||
|
||||
<corpname>{companyname}</corpname>
|
||||
{doctitle#}</articleinfo>
|
||||
|
||||
[footer]
|
||||
</article>
|
||||
|
||||
[preamble]
|
||||
# Untitled elements between header and first section title.
|
||||
|
|
||||
|
||||
[sect-abstract]
|
||||
<abstract{id? id="{id}"}>
|
||||
|
|
||||
</abstract>
|
||||
|
||||
[sect1]
|
||||
<section{id? id="{id}"}>
|
||||
<title>{title}</title>
|
||||
|
|
||||
</section>
|
||||
|
||||
[sect2]
|
||||
<section{id? id="{id}"}>
|
||||
<title>{title}</title>
|
||||
|
|
||||
</section>
|
||||
|
||||
[sect3]
|
||||
<section{id? id="{id}"}>
|
||||
<title>{title}</title>
|
||||
|
|
||||
</section>
|
||||
|
||||
[sect4]
|
||||
<section{id? id="{id}"}>
|
||||
<title>{title}</title>
|
||||
|
|
||||
</section>
|
||||
|
||||
endif::doctype-article[]
|
||||
|
||||
#-------------------------
|
||||
# manpage document type
|
||||
#-------------------------
|
||||
ifdef::doctype-manpage[]
|
||||
|
||||
[replacements]
|
||||
# The roff format does not substitute special characters so just print them as
|
||||
# text.
|
||||
\(C\)=(C)
|
||||
\(TM\)=(TM)
|
||||
|
||||
[header]
|
||||
template::[header-declarations]
|
||||
<refentry>
|
||||
<refmeta>
|
||||
<refentrytitle>{mantitle}</refentrytitle>
|
||||
<manvolnum>{manvolnum}</manvolnum>
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname>{manname}</refname>
|
||||
<refpurpose>{manpurpose}</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
[footer]
|
||||
</refentry>
|
||||
|
||||
# Section macros
|
||||
[sect-synopsis]
|
||||
<refsynopsisdiv{id? id="{id}"}>
|
||||
|
|
||||
</refsynopsisdiv>
|
||||
|
||||
[sect1]
|
||||
<refsect1{id? id="{id}"}>
|
||||
<title>{title}</title>
|
||||
|
|
||||
</refsect1>
|
||||
|
||||
[sect2]
|
||||
<refsect2{id? id="{id}"}>
|
||||
<title>{title}</title>
|
||||
|
|
||||
</refsect2>
|
||||
|
||||
[sect3]
|
||||
<refsect3{id? id="{id}"}>
|
||||
<title>{title}</title>
|
||||
|
|
||||
</refsect3>
|
||||
|
||||
endif::doctype-manpage[]
|
||||
|
||||
#-------------------------
|
||||
# book document type
|
||||
#-------------------------
|
||||
ifdef::doctype-book[]
|
||||
|
||||
[header]
|
||||
template::[header-declarations]
|
||||
|
||||
<book lang="en">
|
||||
{doctitle#}<bookinfo>
|
||||
<title>{doctitle}</title>
|
||||
<date>{date}</date>
|
||||
{authored#}<author>
|
||||
<firstname>{firstname}</firstname>
|
||||
<othername>{middlename}</othername>
|
||||
<surname>{lastname}</surname>
|
||||
<affiliation><address><email>{email}</email></address></affiliation>
|
||||
{authored#}</author>
|
||||
<authorinitials>{authorinitials}</authorinitials>
|
||||
|
||||
# If file named like source document with -revhistory.xml suffix exists
|
||||
# include it as the document history, otherwise use current revision.
|
||||
{revisionhistory#}{include:{docdir}/{docname}-revhistory.xml}
|
||||
{revisionhistory%}<revhistory><revision><revnumber>{revision}</revnumber><date>{date}</date>{authorinitials?<authorinitials>{authorinitials}</authorinitials>}{revremark?<revremark>{revremark}</revremark>}</revision></revhistory>
|
||||
|
||||
<corpname>{companyname}</corpname>
|
||||
{doctitle#}</bookinfo>
|
||||
|
||||
[footer]
|
||||
</book>
|
||||
|
||||
[preamble]
|
||||
# Preamble is not allowed in DocBook book so wrap it in a preface.
|
||||
<preface{id? id="{id}"}>
|
||||
<title>Preface</title>
|
||||
|
|
||||
</preface>
|
||||
|
||||
[sect-dedication]
|
||||
<dedication{id? id="{id}"}>
|
||||
|
|
||||
</dedication>
|
||||
|
||||
[sect-colophon]
|
||||
<colophon{id? id="{id}"}>
|
||||
|
|
||||
</colophon>
|
||||
|
||||
[sect0]
|
||||
<part{id? id="{id}"}>
|
||||
<title>{title}</title>
|
||||
|
|
||||
</part>
|
||||
|
||||
[sect1]
|
||||
<chapter{id? id="{id}"}>
|
||||
<title>{title}</title>
|
||||
|
|
||||
</chapter>
|
||||
|
||||
[sect2]
|
||||
<section{id? id="{id}"}>
|
||||
<title>{title}</title>
|
||||
|
|
||||
</section>
|
||||
|
||||
[sect3]
|
||||
<section{id? id="{id}"}>
|
||||
<title>{title}</title>
|
||||
|
|
||||
</section>
|
||||
|
||||
[sect4]
|
||||
<section{id? id="{id}"}>
|
||||
<title>{title}</title>
|
||||
|
|
||||
</section>
|
||||
|
||||
endif::doctype-book[]
|
||||
|
||||
ifdef::sgml[]
|
||||
#
|
||||
# Optional DocBook SGML.
|
||||
#
|
||||
# Most of the differences between DocBook XML and DocBook SGML boils
|
||||
# down to the empty element syntax: SGML does not like the XML empty
|
||||
# element <.../> syntax, use <...> instead.
|
||||
#
|
||||
[miscellaneous]
|
||||
outfilesuffix=.sgml
|
||||
|
||||
[header-declarations]
|
||||
<!DOCTYPE {doctype-article?article}{doctype-book?book}{doctype-manpage?refentry} PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
|
||||
|
||||
[tabledef-default]
|
||||
colspec=<colspec colwidth="{colwidth}{pageunits}" align="{colalign}">
|
||||
|
||||
[image-inlinemacro]
|
||||
<inlinemediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="{target}"{width? width="{width}pt"}{height? depth="{height}pt"}>
|
||||
</imageobject>
|
||||
<textobject><phrase>{1={target}}</phrase></textobject>
|
||||
</inlinemediaobject>
|
||||
|
||||
[image-blockmacro]
|
||||
<figure><title>{title}</title>
|
||||
{title%}<informalfigure>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="{target}"{width? width="{width}pt"}{height? depth="{height}pt"}>
|
||||
</imageobject>
|
||||
<textobject><phrase>{1={target}}</phrase></textobject>
|
||||
</mediaobject>
|
||||
{title#}</figure>
|
||||
{title%}</informalfigure>
|
||||
|
||||
# Inline macros
|
||||
[xref-inlinemacro]
|
||||
<link linkend="{target}">{0}</link>
|
||||
{2%}<xref linkend="{target}">
|
||||
[xref2-inlinemacro]
|
||||
# <<id,text>>
|
||||
<link linkend="{1}">{2}</link>
|
||||
{2%}<xref linkend="{1}">
|
||||
[anchor-inlinemacro]
|
||||
<anchor id="{target}" xreflabel="{0=[{target}]}">
|
||||
[anchor2-inlinemacro]
|
||||
# [[id,text]]
|
||||
<anchor id="{1}" xreflabel="{2=[{1}]}">
|
||||
|
||||
endif::sgml[]
|
28
doc/tools/asciidoc/stylesheets/xhtml11-quirks.css
Normal file
28
doc/tools/asciidoc/stylesheets/xhtml11-quirks.css
Normal file
@ -0,0 +1,28 @@
|
||||
/* Workarounds for IE6's broken and incomplete CSS2. */
|
||||
|
||||
div.sidebar-content {
|
||||
background: #ffffee;
|
||||
border: 1px solid silver;
|
||||
padding: 0.5em;
|
||||
}
|
||||
div.sidebar-title, div.image-title {
|
||||
font-family: sans-serif;
|
||||
font-weight: bold;
|
||||
margin-top: 0.0em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
div.listingblock div.content {
|
||||
border: 1px solid silver;
|
||||
background: #f4f4f4;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
div.quoteblock-content {
|
||||
padding-left: 2.0em;
|
||||
}
|
||||
|
||||
div.exampleblock-content {
|
||||
border-left: 2px solid silver;
|
||||
padding-left: 0.5em;
|
||||
}
|
229
doc/tools/asciidoc/stylesheets/xhtml11.css
Normal file
229
doc/tools/asciidoc/stylesheets/xhtml11.css
Normal file
@ -0,0 +1,229 @@
|
||||
/* Debug borders */
|
||||
p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 {
|
||||
/*
|
||||
border: 1px solid red;
|
||||
*/
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 1em 5% 1em 5%;
|
||||
}
|
||||
|
||||
a {
|
||||
color: blue;
|
||||
text-decoration: underline;
|
||||
}
|
||||
a:visited {
|
||||
color: fuchsia;
|
||||
}
|
||||
|
||||
em {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
tt {
|
||||
color: navy;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
color: #527bbd;
|
||||
font-family: sans-serif;
|
||||
margin-top: 1.2em;
|
||||
margin-bottom: 0.5em;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
h1 {
|
||||
border-bottom: 2px solid silver;
|
||||
}
|
||||
h2 {
|
||||
border-bottom: 2px solid silver;
|
||||
padding-top: 0.5em;
|
||||
}
|
||||
|
||||
div.sectionbody {
|
||||
font-family: serif;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 1px solid silver;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
span#author {
|
||||
color: #527bbd;
|
||||
font-family: sans-serif;
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
span#email {
|
||||
}
|
||||
span#revision {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
div#footer {
|
||||
font-family: sans-serif;
|
||||
font-size: small;
|
||||
border-top: 2px solid silver;
|
||||
padding-top: 0.5em;
|
||||
margin-top: 4.0em;
|
||||
}
|
||||
div#footer-text {
|
||||
float: left;
|
||||
padding-bottom: 0.5em;
|
||||
}
|
||||
div#footer-badges {
|
||||
float: right;
|
||||
padding-bottom: 0.5em;
|
||||
}
|
||||
|
||||
div#preamble,
|
||||
div.tableblock, div.imageblock, div.exampleblock, div.verseblock,
|
||||
div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
|
||||
div.admonitionblock {
|
||||
margin-right: 10%;
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
div.admonitionblock {
|
||||
margin-top: 2.5em;
|
||||
margin-bottom: 2.5em;
|
||||
}
|
||||
|
||||
div.content { /* Block element content. */
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Block element titles. */
|
||||
div.title, caption.title {
|
||||
font-family: sans-serif;
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
margin-top: 1.0em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
div.title + * {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
td div.title:first-child {
|
||||
margin-top: 0.0em;
|
||||
}
|
||||
div.content div.title:first-child {
|
||||
margin-top: 0.0em;
|
||||
}
|
||||
div.content + div.title {
|
||||
margin-top: 0.0em;
|
||||
}
|
||||
|
||||
div.sidebarblock > div.content {
|
||||
background: #ffffee;
|
||||
border: 1px solid silver;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
div.listingblock > div.content {
|
||||
border: 1px solid silver;
|
||||
background: #f4f4f4;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
div.quoteblock > div.content {
|
||||
padding-left: 2.0em;
|
||||
}
|
||||
|
||||
div.attribution {
|
||||
text-align: right;
|
||||
}
|
||||
div.verseblock + div.attribution {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.admonitionblock .icon {
|
||||
vertical-align: top;
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
text-decoration: underline;
|
||||
color: #527bbd;
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
div.admonitionblock td.content {
|
||||
padding-left: 0.5em;
|
||||
border-left: 2px solid silver;
|
||||
}
|
||||
|
||||
div.exampleblock > div.content {
|
||||
border-left: 2px solid silver;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
div.verseblock div.content {
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
div.imageblock div.content { padding-left: 0; }
|
||||
div.imageblock img { border: 1px solid silver; }
|
||||
span.image img { border-style: none; }
|
||||
|
||||
dl {
|
||||
margin-top: 0.8em;
|
||||
margin-bottom: 0.8em;
|
||||
}
|
||||
dt {
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0;
|
||||
font-style: italic;
|
||||
}
|
||||
dd > *:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
list-style-position: outside;
|
||||
}
|
||||
ol.olist2 {
|
||||
list-style-type: lower-alpha;
|
||||
}
|
||||
|
||||
div.tableblock > table {
|
||||
border: 3px solid #527bbd;
|
||||
}
|
||||
thead {
|
||||
font-family: sans-serif;
|
||||
font-weight: bold;
|
||||
}
|
||||
tfoot {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.hlist {
|
||||
margin-top: 0.8em;
|
||||
margin-bottom: 0.8em;
|
||||
}
|
||||
td.hlist1 {
|
||||
vertical-align: top;
|
||||
font-style: italic;
|
||||
padding-right: 0.8em;
|
||||
}
|
||||
td.hlist2 {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
@media print {
|
||||
div#footer-badges { display: none; }
|
||||
}
|
43
doc/tools/asciidoc/xhtml11-quirks.conf
Normal file
43
doc/tools/asciidoc/xhtml11-quirks.conf
Normal file
@ -0,0 +1,43 @@
|
||||
#
|
||||
# xhtml11-quirks.conf
|
||||
#
|
||||
# Workarounds for IE6's broken # and incomplete CSS2.
|
||||
#
|
||||
|
||||
[image-blockmacro]
|
||||
<div class="imageblock">
|
||||
<a id="{id}"></a>
|
||||
<div class="content">
|
||||
<a class="image" href="{link}">
|
||||
<img src="{target}" alt="{1={target}}"{1? title="{1}"}{width? width="{width}"}{height? height="{height}"}/>
|
||||
{link#}</a>
|
||||
</div>
|
||||
<div class="image-title">{caption=Figure: }{title}</div>
|
||||
</div>
|
||||
|
||||
[sidebarblock]
|
||||
<div class="sidebarblock">
|
||||
<a id="{id}"></a>
|
||||
<div class="sidebar-content">
|
||||
<div class="sidebar-title">{title}</div>
|
||||
|
|
||||
</div></div>
|
||||
|
||||
[quoteblock]
|
||||
<div class="quoteblock">
|
||||
<a id="{id}"></a>
|
||||
<div class="title">{title}</div>
|
||||
<div class="quoteblock-content">
|
||||
|
|
||||
<div class="attribution">
|
||||
<span class="emphasis">{citetitle}</span><br />
|
||||
— {attribution}
|
||||
</div></div></div>
|
||||
|
||||
[exampleblock]
|
||||
<div class="exampleblock">
|
||||
<a id="{id}"></a>
|
||||
<div class="title">{caption=Example: }{title}</div>
|
||||
<div class="exampleblock-content">
|
||||
|
|
||||
</div></div>
|
426
doc/tools/asciidoc/xhtml11.conf
Normal file
426
doc/tools/asciidoc/xhtml11.conf
Normal file
@ -0,0 +1,426 @@
|
||||
#
|
||||
# xhtml11.conf
|
||||
#
|
||||
# Asciidoc configuration file.
|
||||
# xhtml11 backend, generates XHTML 1.1 conformant markup.
|
||||
#
|
||||
[miscellaneous]
|
||||
outfilesuffix=.html
|
||||
# Screen width in pixels.
|
||||
pagewidth=800
|
||||
pageunits=
|
||||
|
||||
[attributes]
|
||||
basebackend=html
|
||||
basebackend-html=
|
||||
|
||||
[replacements]
|
||||
# Line break.
|
||||
(?m)^(.*)\s\+$=\1<br />
|
||||
# Superscripts.
|
||||
\^(.+?)\^=<sup>\1</sup>
|
||||
# Subscripts.
|
||||
~(.+?)~=<sub>\1</sub>
|
||||
# Escape ASCIIMathML delimiters.
|
||||
ifdef::asciimath[]
|
||||
\$=\$
|
||||
`=\`
|
||||
endif::asciimath[]
|
||||
|
||||
[ruler-blockmacro]
|
||||
<hr />
|
||||
|
||||
[image-inlinemacro]
|
||||
<span class="image">
|
||||
<a class="image" href="{link}">
|
||||
<img src="{target}" alt="{1={target}}"{1? title="{1}"}{width? width="{width}"}{height? height="{height}"}/>
|
||||
{link#}</a>
|
||||
</span>
|
||||
|
||||
[image-blockmacro]
|
||||
<div class="imageblock">
|
||||
<a id="{id}"></a>
|
||||
<div class="content">
|
||||
<a class="image" href="{link}">
|
||||
<img src="{target}" alt="{1={target}}"{1? title="{1}"}{width? width="{width}"}{height? height="{height}"}/>
|
||||
{link#}</a>
|
||||
</div>
|
||||
<div class="title">{caption=Figure: }{title}</div>
|
||||
</div>
|
||||
|
||||
[indexterm-inlinemacro]
|
||||
# Inline index term.
|
||||
{empty}
|
||||
|
||||
[indexterm2-inlinemacro]
|
||||
# Inline index term.
|
||||
# Single entry index term that is visible in the primary text flow.
|
||||
{1}
|
||||
|
||||
[footnote-inlinemacro]
|
||||
# Inline footnote.
|
||||
<br />[{0}]<br />
|
||||
|
||||
[callout-inlinemacro]
|
||||
# Inline callout.
|
||||
<b>({index})</b>
|
||||
|
||||
[tags]
|
||||
# Bulleted, numbered and labeled list tags.
|
||||
ilist={id?<a id="{id}"></a>}{title?<div class="title">{title}</div>}<ul>|</ul>
|
||||
ilistitem=<li>|</li>
|
||||
ilisttext=<p>|</p>
|
||||
olist={id?<a id="{id}"></a>}{title?<div class="title">{title}</div>}<ol>|</ol>
|
||||
olist2={id?<a id="{id}"></a>}<ol class="olist2">|</ol>
|
||||
olistitem=<li>|</li>
|
||||
olisttext=<p>|</p>
|
||||
vlist={id?<a id="{id}"></a>}{title?<div class="title">{title}</div>}<dl>|</dl>
|
||||
vlistentry=|
|
||||
vlistterm=<dt>|</dt>
|
||||
vlistitem=<dd>|</dd>
|
||||
vlisttext=<p>|</p>
|
||||
# Horizontal labeled list.
|
||||
hlist=<div class="hlist">{id?<a id="{id}"></a>}{title?<div class="title">{title}</div>}<table>{1?<col width="{1}%" />}{2?<col width="{2}%" />}|</table></div>
|
||||
hlistentry=<tr>|</tr>
|
||||
hlistterm=<td class="hlist1">|</td>
|
||||
hlistitem=<td class="hlist2">|</td>
|
||||
hlisttext=|
|
||||
# Question and Answer list.
|
||||
qlist={id?<a id="{id}"></a>}{title?<div class="title">{title}</div>}<ol>|</ol>
|
||||
qlistentry=<li>|</li>
|
||||
qlistterm=<p><strong>|</strong></p>
|
||||
qlistitem=|
|
||||
qlisttext=<p>|</p>
|
||||
# Callout list.
|
||||
colist={id?<a id="{id}"></a>}{title?<div class="title">{title}</div>}<ol>|</ol>
|
||||
colistitem=<li>|</li>
|
||||
colisttext=<p>|</p>
|
||||
|
||||
# Quoted text.
|
||||
emphasis=<em{0? style="}{1?color: {1};}{2?background-color: {2};}{3?font-size: {3}em;}{0?"}>|</em>
|
||||
strong=<strong{0? style="}{1?color: {1};}{2?background-color: {2};}{3?font-size: {3}em;}{0?"}>|</strong>
|
||||
monospaced=<tt{0? style="}{1?color: {1};}{2?background-color: {2};}{3?font-size: {3}em;}{0?"}>|</tt>
|
||||
quoted={0?<span style="}{1?color: {1};}{2?background-color: {2};}{3?font-size: {3}em;}{0?">}{amp}#8220;|{amp}#8221;{0?</span>}
|
||||
unquoted={0?<span style="}{1?color: {1};}{2?background-color: {2};}{3?font-size: {3}em;}{0?">}|{0?</span>}
|
||||
|
||||
# $$ inline passthrough.
|
||||
$$passthrough=<span{0? style="}{1?color: {1};}{2?background-color: {2};}{3?font-size: {3}em;}{0?"}>|</span>
|
||||
|
||||
# Inline macros
|
||||
[http-inlinemacro]
|
||||
<a href="{name}:{target}">{0={name}:{target}}</a>
|
||||
[https-inlinemacro]
|
||||
<a href="{name}:{target}">{0={name}:{target}}</a>
|
||||
[ftp-inlinemacro]
|
||||
<a href="{name}:{target}">{0={name}:{target}}</a>
|
||||
[file-inlinemacro]
|
||||
<a href="{name}:{target}">{0={name}:{target}}</a>
|
||||
[mailto-inlinemacro]
|
||||
<a href="{name}:{target}">{0={target}}</a>
|
||||
[link-inlinemacro]
|
||||
<a href="{target}">{0={target}}</a>
|
||||
# anchor:id[text]
|
||||
[anchor-inlinemacro]
|
||||
<a id="{target}"></a>
|
||||
# [[id,text]]
|
||||
[anchor2-inlinemacro]
|
||||
<a id="{1}"></a>
|
||||
# [[[id]]]
|
||||
[anchor3-inlinemacro]
|
||||
<a id="{1}">[{1}]</a>
|
||||
# xref:id[text]
|
||||
[xref-inlinemacro]
|
||||
<a href="#{target}">{0=[{target}]}</a>
|
||||
# <<id,text>>
|
||||
[xref2-inlinemacro]
|
||||
<a href="#{1}">{2=[{1}]}</a>
|
||||
|
||||
# Special word substitution.
|
||||
[emphasizedwords]
|
||||
<em>{words}</em>
|
||||
[monospacedwords]
|
||||
<tt>{words}</tt>
|
||||
[strongwords]
|
||||
<strong>{words}</strong>
|
||||
|
||||
# Paragraph substitution.
|
||||
[paragraph]
|
||||
<div class="title">{title}</div>
|
||||
<p>{id?<a id="{id}"></a>}
|
||||
|
|
||||
</p>
|
||||
|
||||
[literalparagraph]
|
||||
# The literal block employs the same markup.
|
||||
template::[literalblock]
|
||||
|
||||
[verseparagraph]
|
||||
# The verse block employs the same markup.
|
||||
template::[verseblock]
|
||||
|
||||
[admonitionparagraph]
|
||||
# The admonition block employs the same markup.
|
||||
template::[admonitionblock]
|
||||
|
||||
# Delimited blocks.
|
||||
[passthroughblock]
|
||||
|
|
||||
|
||||
[listingblock]
|
||||
<div class="listingblock">
|
||||
<a id="{id}"></a>
|
||||
<div class="title">{caption=Example: }{title}</div>
|
||||
<div class="content">
|
||||
<pre><tt>
|
||||
|
|
||||
</tt></pre>
|
||||
</div></div>
|
||||
|
||||
[literalblock]
|
||||
<div class="literalblock">
|
||||
<a id="{id}"></a>
|
||||
<div class="title">{title}</div>
|
||||
<div class="content">
|
||||
{style#}<pre class="{style}"><span>
|
||||
{style%}<pre><tt>
|
||||
|
|
||||
</tt></pre>
|
||||
</div></div>
|
||||
|
||||
[verseblock]
|
||||
<div class="verseblock">
|
||||
<a id="{id}"></a>
|
||||
<div class="title">{title}</div>
|
||||
<div class="content">
|
||||
|
|
||||
</div></div>
|
||||
|
||||
[sidebarblock]
|
||||
<div class="sidebarblock">
|
||||
<a id="{id}"></a>
|
||||
<div class="content">
|
||||
<div class="title">{title}</div>
|
||||
|
|
||||
</div></div>
|
||||
|
||||
[quoteblock]
|
||||
<div class="quoteblock">
|
||||
<a id="{id}"></a>
|
||||
<div class="title">{title}</div>
|
||||
<div class="content">
|
||||
|
|
||||
<div class="attribution">
|
||||
<em>{citetitle}</em><br />
|
||||
— {attribution}
|
||||
</div></div></div>
|
||||
|
||||
[exampleblock]
|
||||
<div class="exampleblock">
|
||||
<a id="{id}"></a>
|
||||
<div class="title">{caption=Example: }{title}</div>
|
||||
<div class="content">
|
||||
|
|
||||
</div></div>
|
||||
|
||||
[admonitionblock]
|
||||
<div class="admonitionblock">
|
||||
<a id="{id}"></a>
|
||||
<table><tr>
|
||||
<td class="icon">
|
||||
{icons#}<img src="{icon={iconsdir}/{name}.png}" alt="{caption}" />
|
||||
{icons%}<div class="title">{caption}</div>
|
||||
</td>
|
||||
<td class="content">
|
||||
<div class="title">{title}</div>
|
||||
|
|
||||
</td>
|
||||
</tr></table>
|
||||
</div>
|
||||
|
||||
# Bibliography list.
|
||||
# Same as numbered list.
|
||||
[listdef-bibliography]
|
||||
listtag=olist
|
||||
itemtag=olistitem
|
||||
texttag=olisttext
|
||||
|
||||
# Glossary list.
|
||||
# Same as labeled list.
|
||||
[listdef-glossary]
|
||||
listtag=vlist
|
||||
itemtag=vlistitem
|
||||
texttag=vlisttext
|
||||
entrytag=vlistentry
|
||||
labeltag=vlistterm
|
||||
|
||||
# Tables.
|
||||
[tabledef-default]
|
||||
template=table
|
||||
colspec=<col width="{colwidth}{pageunits}" />
|
||||
bodyrow=<tr>|</tr>
|
||||
headdata=<th align="{colalign}">|</th>
|
||||
footdata=<td align="{colalign}">|</td>
|
||||
bodydata=<td align="{colalign}">|</td>
|
||||
|
||||
[table]
|
||||
<div class="tableblock">
|
||||
<a id="{id}"></a>
|
||||
<table rules="{grid=none}"
|
||||
frame="{frame%hsides}"
|
||||
frame="{frame@topbot:hsides}{frame@all:border}{frame@none:void}{frame@sides:vsides}"
|
||||
cellspacing="0" cellpadding="4">
|
||||
<caption class="title">{caption=Table: }{title}</caption>
|
||||
{colspecs}
|
||||
{headrows#}<thead>
|
||||
{headrows}
|
||||
{headrows#}</thead>
|
||||
{footrows#}<tfoot>
|
||||
{footrows}
|
||||
{footrows#}</tfoot>
|
||||
<tbody valign="top">
|
||||
{bodyrows}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
[preamble]
|
||||
# Untitled elements between header and first section title.
|
||||
<div id="preamble">
|
||||
<a id="{id}"></a>
|
||||
<div class="sectionbody">
|
||||
|
|
||||
</div>
|
||||
</div>
|
||||
|
||||
# Document sections.
|
||||
[sect0]
|
||||
<h1>{id?<a id="{id}"></a>}{title}</h1>
|
||||
|
|
||||
|
||||
[sect1]
|
||||
<h2>{id?<a id="{id}"></a>}{numbered?{sectnum} }{title}</h2>
|
||||
<div class="sectionbody">
|
||||
|
|
||||
</div>
|
||||
|
||||
[sect2]
|
||||
<h3>{id?<a id="{id}"></a>}{numbered?{sectnum} }{title}</h3>
|
||||
|
|
||||
|
||||
[sect3]
|
||||
<h4>{id?<a id="{id}"></a>}{numbered?{sectnum} }{title}</h4>
|
||||
|
|
||||
|
||||
[sect4]
|
||||
<h5>{id?<a id="{id}"></a>}{title}</h5>
|
||||
|
|
||||
|
||||
[header]
|
||||
# IE6 enters quirks mode if the following XML directive is present.
|
||||
#<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
|
||||
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset={encoding}" />
|
||||
<meta name="generator" content="AsciiDoc {asciidoc-version}" />
|
||||
ifdef::linkcss[]
|
||||
<link rel="stylesheet" href="{stylesdir=.}/{theme={backend}}.css" type="text/css" />
|
||||
{doctype-manpage}<link rel="stylesheet" href="{stylesdir=.}/{theme={backend}}-manpage.css" type="text/css" />
|
||||
ifdef::quirks[]
|
||||
<link rel="stylesheet" href="{stylesdir=.}/{theme={backend}}-quirks.css" type="text/css" />
|
||||
endif::quirks[]
|
||||
endif::linkcss[]
|
||||
ifndef::linkcss[]
|
||||
<style type="text/css">
|
||||
include1::{stylesdir=./stylesheets}/{theme={backend}}.css[]
|
||||
{doctype-manpage}include1::{stylesdir=./stylesheets}/{theme={backend}}-manpage.css[]
|
||||
ifdef::quirks[]
|
||||
include1::{stylesdir=./stylesheets}/{theme={backend}}-quirks.css[]
|
||||
endif::quirks[]
|
||||
</style>
|
||||
endif::linkcss[]
|
||||
ifdef::asciimath[]
|
||||
ifdef::linkcss[]
|
||||
<script type="text/javascript" src="{scriptsdir=.}/ASCIIMathML.js"></script>
|
||||
endif::linkcss[]
|
||||
ifndef::linkcss[]
|
||||
<script type="text/javascript">
|
||||
# Escape as CDATA to pass validators.
|
||||
/*<![CDATA[*/
|
||||
include1::{scriptsdir=./javascripts}/ASCIIMathML.js[]
|
||||
/*]]>*/
|
||||
</script>
|
||||
endif::linkcss[]
|
||||
endif::asciimath[]
|
||||
<title>{doctitle}</title>
|
||||
</head>
|
||||
<body>
|
||||
# Article, book header.
|
||||
ifndef::doctype-manpage[]
|
||||
<div id="header">
|
||||
<h1>{doctitle}</h1>
|
||||
<span id="author">{author}</span><br />
|
||||
<span id="email"><tt><<a href="mailto:{email}">{email}</a>></tt></span><br />
|
||||
<span id="revision">version {revision}{date?,}</span>
|
||||
{date}
|
||||
</div>
|
||||
endif::doctype-manpage[]
|
||||
# Man page header.
|
||||
ifdef::doctype-manpage[]
|
||||
<div id="header">
|
||||
<h1>
|
||||
{doctitle} Manual Page
|
||||
</h1>
|
||||
<h2>NAME</h2>
|
||||
<div class="sectionbody">
|
||||
<p>{manname} -
|
||||
{manpurpose}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
endif::doctype-manpage[]
|
||||
|
||||
[footer]
|
||||
<div id="footer">
|
||||
<div id="footer-text">
|
||||
Version {revision}<br />
|
||||
Last updated {localdate} {localtime}
|
||||
</div>
|
||||
ifdef::badges[]
|
||||
<div id="footer-badges">
|
||||
ifndef::icons[]
|
||||
Valid <a href="http://validator.w3.org/check?uri=referer">XHTML</a>
|
||||
and <a href="http://jigsaw.w3.org/css-validator/check/referer">CSS</a>.
|
||||
endif::icons[]
|
||||
ifdef::icons[]
|
||||
<a href="http://validator.w3.org/check?uri=referer">
|
||||
<img style="border:none; width:88px; height:31px;"
|
||||
src="http://www.w3.org/Icons/valid-xhtml11"
|
||||
alt="Valid XHTML 1.1!" />
|
||||
</a>
|
||||
<a href="http://jigsaw.w3.org/css-validator/check/referer">
|
||||
<img style="border:none; width:88px; height:31px;"
|
||||
src="http://jigsaw.w3.org/css-validator/images/vcss"
|
||||
alt="Valid CSS!" />
|
||||
</a>
|
||||
<a href="http://www.mozilla.org/products/firefox/">
|
||||
<img style="border:none; width:110px; height:32px;"
|
||||
src="http://www.spreadfirefox.com/community/images/affiliates/Buttons/110x32/safer.gif"
|
||||
alt="Get Firefox!" />
|
||||
</a>
|
||||
endif::icons[]
|
||||
</div>
|
||||
endif::badges[]
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
ifdef::doctype-manpage[]
|
||||
[sect-synopsis]
|
||||
template::[sect1]
|
||||
endif::doctype-manpage[]
|
||||
|
||||
ifdef::quirks[]
|
||||
include::{backend}-quirks.conf[]
|
||||
endif::quirks[]
|
@ -132,7 +132,7 @@ download_dialog_layouter(struct dialog_data *dlg_data)
|
||||
&& download->progress->size >= 0);
|
||||
#if CONFIG_BITTORRENT
|
||||
int bittorrent = (file_download->uri->protocol == PROTOCOL_BITTORRENT
|
||||
&& (show_meter || download->state == S_RESUME));
|
||||
&& (show_meter || is_in_state(download->state, S_RESUME)));
|
||||
#endif
|
||||
|
||||
redraw_below_window(dlg_data->win);
|
||||
@ -402,7 +402,7 @@ draw_file_download(struct listbox_item *item, struct listbox_context *context,
|
||||
|
||||
if (!download->progress
|
||||
|| download->progress->size < 0
|
||||
|| download->state != S_TRANS
|
||||
|| !is_in_state(download->state, S_TRANS)
|
||||
|| !has_progress(download->progress)) {
|
||||
/* TODO: Show trimmed error message. */
|
||||
return;
|
||||
|
@ -74,7 +74,8 @@ save_url(struct session *ses, unsigned char *url)
|
||||
|
||||
uri = get_translated_uri(url, ses->tab->term->cwd);
|
||||
if (!uri) {
|
||||
print_error_dialog(ses, S_BAD_URL, uri, PRI_CANCEL);
|
||||
print_error_dialog(ses, connection_state(S_BAD_URL),
|
||||
uri, PRI_CANCEL);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -568,12 +569,14 @@ query_file(struct session *ses, struct uri *uri, void *data,
|
||||
* the checking? --jonas */
|
||||
|
||||
if (uri->protocol == PROTOCOL_UNKNOWN) {
|
||||
print_error_dialog(ses, S_UNKNOWN_PROTOCOL, uri, PRI_CANCEL);
|
||||
print_error_dialog(ses, connection_state(S_UNKNOWN_PROTOCOL),
|
||||
uri, PRI_CANCEL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (get_protocol_external_handler(ses->tab->term, uri)) {
|
||||
print_error_dialog(ses, S_EXTERNAL_PROTOCOL, uri, PRI_CANCEL);
|
||||
print_error_dialog(ses, connection_state(S_EXTERNAL_PROTOCOL),
|
||||
uri, PRI_CANCEL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -217,12 +217,12 @@ display_status_bar(struct session *ses, struct terminal *term, int tabs_count)
|
||||
static int last_current_link;
|
||||
int ncl = doc_view->vs->current_link;
|
||||
|
||||
if (download->state == S_INTERRUPTED
|
||||
if (is_in_state(download->state, S_INTERRUPTED)
|
||||
&& ncl != last_current_link)
|
||||
download->state = S_OK;
|
||||
download->state = connection_state(S_OK);
|
||||
last_current_link = ncl;
|
||||
|
||||
if (download->state == S_OK) {
|
||||
if (is_in_state(download->state, S_OK)) {
|
||||
if (get_current_link(doc_view)) {
|
||||
msg = get_current_link_info_and_title(ses, doc_view);
|
||||
} else if (ses->navigate_mode == NAVIGATE_CURSOR_ROUTING) {
|
||||
@ -344,7 +344,7 @@ display_tab_bar(struct session *ses, struct terminal *term, int tabs_count)
|
||||
} else {
|
||||
download = get_current_download(tab_ses);
|
||||
|
||||
if (download && download->state != S_OK) {
|
||||
if (download && !is_in_state(download->state, S_OK)) {
|
||||
color = loading_color;
|
||||
} else if (!tab_ses || !tab_ses->status.visited) {
|
||||
color = fresh_color;
|
||||
|
@ -165,7 +165,7 @@ import_css_file(struct css_stylesheet *css, struct uri *base_uri,
|
||||
|
||||
add_bytes_to_string(&filename, url, urllen);
|
||||
|
||||
if (read_encoded_file(&filename, &string) == S_OK) {
|
||||
if (is_in_state(read_encoded_file(&filename, &string), S_OK)) {
|
||||
unsigned char *end = string.source + string.length;
|
||||
|
||||
css->import_level++;
|
||||
|
@ -33,8 +33,6 @@
|
||||
#include "util/string.h"
|
||||
#include "viewer/text/link.h"
|
||||
|
||||
static int document_init_counter = 0;
|
||||
|
||||
static INIT_LIST_OF(struct document, format_cache);
|
||||
|
||||
struct document *
|
||||
@ -56,7 +54,6 @@ init_document(struct cache_entry *cached, struct document_options *options)
|
||||
|
||||
#ifdef CONFIG_ECMASCRIPT
|
||||
init_list(document->onload_snippets);
|
||||
document->document_id = ++document_init_counter;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_COMBINE
|
||||
|
@ -166,7 +166,6 @@ struct document {
|
||||
struct uri_list ecmascript_imports;
|
||||
/** used by setTimeout */
|
||||
timer_id_T timeout;
|
||||
unsigned int document_id;
|
||||
#endif
|
||||
#ifdef CONFIG_CSS
|
||||
/** @todo FIXME: We should externally maybe using cache_entry store the
|
||||
|
@ -390,11 +390,11 @@ render_document(struct view_state *vs, struct document_view *doc_view,
|
||||
* other tab when we press ^L here? */
|
||||
if (vs->ecmascript_fragile
|
||||
|| (vs->ecmascript
|
||||
&& vs->ecmascript->onload_snippets_document_id
|
||||
&& document->document_id != vs->ecmascript->onload_snippets_document_id))
|
||||
&& vs->ecmascript->onload_snippets_cache_id
|
||||
&& document->cache_id != vs->ecmascript->onload_snippets_cache_id))
|
||||
ecmascript_reset_state(vs);
|
||||
assert(vs->ecmascript);
|
||||
vs->ecmascript->onload_snippets_document_id = document->document_id;
|
||||
vs->ecmascript->onload_snippets_cache_id = document->cache_id;
|
||||
|
||||
/* Passing of the onload_snippets pointers gives *_snippets()
|
||||
* some feeling of universality, shall we ever get any other
|
||||
|
@ -66,53 +66,6 @@ static struct option_info ecmascript_options[] = {
|
||||
NULL_OPTION_INFO,
|
||||
};
|
||||
|
||||
#define NUMBER_OF_URLS_TO_REMEMBER 8
|
||||
static struct {
|
||||
unsigned char *url;
|
||||
unsigned char *frame;
|
||||
} u[NUMBER_OF_URLS_TO_REMEMBER];
|
||||
static int url_index = 0;
|
||||
|
||||
int
|
||||
ecmascript_check_url(unsigned char *url, unsigned char *frame)
|
||||
{
|
||||
int i;
|
||||
/* Because of gradual rendering window.open is called many
|
||||
* times with the same arguments.
|
||||
* This workaround remembers NUMBER_OF_URLS_TO_REMEMBER last
|
||||
* opened URLs and do not let open them again.
|
||||
*/
|
||||
|
||||
for (i = 0; i < NUMBER_OF_URLS_TO_REMEMBER; i++) {
|
||||
if (!u[i].url) break;
|
||||
if (!strcmp(u[i].url, url) && !strcmp(u[i].frame, frame)) {
|
||||
mem_free(url);
|
||||
mem_free(frame);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
mem_free_if(u[url_index].url);
|
||||
mem_free_if(u[url_index].frame);
|
||||
u[url_index].url = url;
|
||||
u[url_index].frame = frame;
|
||||
url_index++;
|
||||
if (url_index >= NUMBER_OF_URLS_TO_REMEMBER) url_index = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
ecmascript_free_urls(struct module *module)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUMBER_OF_URLS_TO_REMEMBER; i++) {
|
||||
mem_free_if(u[i].url);
|
||||
mem_free_if(u[i].frame);
|
||||
}
|
||||
}
|
||||
|
||||
#undef NUMBER_OF_URLS_TO_REMEMBER
|
||||
|
||||
struct ecmascript_interpreter *
|
||||
ecmascript_get_interpreter(struct view_state *vs)
|
||||
{
|
||||
@ -401,5 +354,5 @@ struct module ecmascript_module = struct_module(
|
||||
/* submodules: */ ecmascript_modules,
|
||||
/* data: */ NULL,
|
||||
/* init: */ NULL,
|
||||
/* done: */ ecmascript_free_urls
|
||||
/* done: */ NULL
|
||||
);
|
||||
|
@ -52,7 +52,7 @@ struct ecmascript_interpreter {
|
||||
* ecmascript_fragile, but it can happen i.e. when the urrent document
|
||||
* is reloaded in another tab and then you just cause the current tab
|
||||
* to redraw. */
|
||||
unsigned int onload_snippets_document_id;
|
||||
unsigned int onload_snippets_cache_id;
|
||||
};
|
||||
|
||||
/* Why is the interpreter bound to {struct view_state} instead of {struct
|
||||
|
@ -241,14 +241,12 @@ js_window_open(struct SEE_interpreter *interp, struct SEE_object *self,
|
||||
struct view_state *vs = win->vs;
|
||||
struct document_view *doc_view = vs->doc_view;
|
||||
struct session *ses = doc_view->session;
|
||||
unsigned char *frame = "";
|
||||
unsigned char *frame = NULL;
|
||||
unsigned char *url, *url2;
|
||||
struct uri *uri;
|
||||
struct SEE_value url_value;
|
||||
#if 0
|
||||
static time_t ratelimit_start;
|
||||
static int ratelimit_count;
|
||||
#endif
|
||||
|
||||
/* Do not check thisobj->objectclass. ELinks sets this
|
||||
* function as a property of both the window object and the
|
||||
@ -263,7 +261,7 @@ js_window_open(struct SEE_interpreter *interp, struct SEE_object *self,
|
||||
}
|
||||
|
||||
if (argc < 1) return;
|
||||
#if 0
|
||||
|
||||
/* Ratelimit window opening. Recursive window.open() is very nice.
|
||||
* We permit at most 20 tabs in 2 seconds. The ratelimiter is very
|
||||
* rough but shall suffice against the usual cases. */
|
||||
@ -276,7 +274,7 @@ js_window_open(struct SEE_interpreter *interp, struct SEE_object *self,
|
||||
if (ratelimit_count > 20)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
SEE_ToString(interp, argv[0], &url_value);
|
||||
url = see_string_to_unsigned_char(url_value.u.string);
|
||||
if (!url) return;
|
||||
@ -290,19 +288,23 @@ js_window_open(struct SEE_interpreter *interp, struct SEE_object *self,
|
||||
mem_free(url);
|
||||
return;
|
||||
}
|
||||
/* url and frame will be freed by ecmascript_check_url */
|
||||
if (!ecmascript_check_url(url, frame)) return;
|
||||
}
|
||||
/* TODO: Support for window naming and perhaps some window features? */
|
||||
|
||||
url2 = join_urls(doc_view->document->uri, url);
|
||||
mem_free(url);
|
||||
if (!url2) return;
|
||||
if (!url2) {
|
||||
mem_free_if(frame);
|
||||
return;
|
||||
}
|
||||
uri = get_uri(url2, 0);
|
||||
mem_free(url2);
|
||||
if (!uri) return;
|
||||
if (!uri) {
|
||||
mem_free_if(frame);
|
||||
return;
|
||||
}
|
||||
|
||||
if (*frame && strcasecmp(frame, "_blank")) {
|
||||
if (frame && *frame && strcasecmp(frame, "_blank")) {
|
||||
struct delayed_open *deo = mem_calloc(1, sizeof(*deo));
|
||||
|
||||
if (deo) {
|
||||
@ -335,6 +337,7 @@ js_window_open(struct SEE_interpreter *interp, struct SEE_object *self,
|
||||
|
||||
end:
|
||||
done_uri(uri);
|
||||
mem_free_if(frame);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -341,7 +341,7 @@ window_open(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
struct view_state *vs;
|
||||
struct document_view *doc_view;
|
||||
struct session *ses;
|
||||
unsigned char *frame = "";
|
||||
unsigned char *frame = NULL;
|
||||
unsigned char *url, *url2;
|
||||
struct uri *uri;
|
||||
static time_t ratelimit_start;
|
||||
@ -362,17 +362,6 @@ window_open(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
|
||||
if (argc < 1) return JS_TRUE;
|
||||
|
||||
url = stracpy(jsval_to_string(ctx, &argv[0]));
|
||||
trim_chars(url, ' ', 0);
|
||||
if (argc > 1) {
|
||||
frame = stracpy(jsval_to_string(ctx, &argv[1]));
|
||||
if (!frame) {
|
||||
mem_free(url);
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (!ecmascript_check_url(url, frame)) return JS_TRUE;
|
||||
}
|
||||
|
||||
/* Ratelimit window opening. Recursive window.open() is very nice.
|
||||
* We permit at most 20 tabs in 2 seconds. The ratelimiter is very
|
||||
* rough but shall suffice against the usual cases. */
|
||||
@ -381,23 +370,36 @@ window_open(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
ratelimit_count = 0;
|
||||
} else {
|
||||
ratelimit_count++;
|
||||
if (ratelimit_count > 20)
|
||||
if (ratelimit_count > 20) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Support for window naming and perhaps some window features? */
|
||||
|
||||
url = stracpy(jsval_to_string(ctx, &argv[0]));
|
||||
trim_chars(url, ' ', 0);
|
||||
url2 = join_urls(doc_view->document->uri, url);
|
||||
mem_free(url);
|
||||
if (!url2) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (argc > 1) {
|
||||
frame = stracpy(jsval_to_string(ctx, &argv[1]));
|
||||
if (!frame) {
|
||||
mem_free(url2);
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Support for window naming and perhaps some window features? */
|
||||
|
||||
uri = get_uri(url2, 0);
|
||||
mem_free(url2);
|
||||
if (!uri) return JS_TRUE;
|
||||
if (!uri) {
|
||||
mem_free_if(frame);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
||||
if (*frame && strcasecmp(frame, "_blank")) {
|
||||
if (frame && *frame && strcasecmp(frame, "_blank")) {
|
||||
struct delayed_open *deo = mem_calloc(1, sizeof(*deo));
|
||||
|
||||
if (deo) {
|
||||
@ -434,6 +436,7 @@ window_open(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
|
||||
end:
|
||||
done_uri(uri);
|
||||
mem_free_if(frame);
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
@ -223,10 +223,10 @@ try_encoding_extensions(struct string *filename, int *fd)
|
||||
* whether the true end of the stream has been reached.
|
||||
*
|
||||
* @return a connection state. S_OK if all is well. */
|
||||
enum connection_state
|
||||
struct connection_state
|
||||
read_file(struct stream_encoded *stream, int readsize, struct string *page)
|
||||
{
|
||||
if (!init_string(page)) return S_OUT_OF_MEM;
|
||||
if (!init_string(page)) return connection_state(S_OUT_OF_MEM);
|
||||
|
||||
/* We read with granularity of stt.st_size (given as @readsize) - this
|
||||
* does best job for uncompressed files, and doesn't hurt for
|
||||
@ -248,17 +248,17 @@ read_file(struct stream_encoded *stream, int readsize, struct string *page)
|
||||
* do. Since errno == 0 == S_WAIT and we cannot have
|
||||
* that. */
|
||||
if (errno)
|
||||
return (enum connection_state) -errno;
|
||||
return connection_state_for_errno(errno);
|
||||
|
||||
/* FIXME: This is indeed an internal error. If readed from a
|
||||
* corrupted encoded file nothing or only some of the
|
||||
* data will be read. */
|
||||
return S_ENCODE_ERROR;
|
||||
return connection_state(S_ENCODE_ERROR);
|
||||
|
||||
} else if (readlen == 0) {
|
||||
/* NUL-terminate just in case */
|
||||
page->source[page->length] = '\0';
|
||||
return S_OK;
|
||||
return connection_state(S_OK);
|
||||
}
|
||||
|
||||
page->length += readlen;
|
||||
@ -276,7 +276,7 @@ read_file(struct stream_encoded *stream, int readsize, struct string *page)
|
||||
}
|
||||
|
||||
done_string(page);
|
||||
return S_OUT_OF_MEM;
|
||||
return connection_state(S_OUT_OF_MEM);
|
||||
}
|
||||
|
||||
static inline int
|
||||
@ -291,14 +291,14 @@ is_stdin_pipe(struct stat *stt, struct string *filename)
|
||||
S_ISFIFO(stt->st_mode));
|
||||
}
|
||||
|
||||
enum connection_state
|
||||
struct connection_state
|
||||
read_encoded_file(struct string *filename, struct string *page)
|
||||
{
|
||||
struct stream_encoded *stream;
|
||||
struct stat stt;
|
||||
enum stream_encoding encoding = ENCODING_NONE;
|
||||
int fd = open(filename->source, O_RDONLY | O_NOCTTY);
|
||||
enum connection_state state = -errno;
|
||||
struct connection_state state = connection_state_for_errno(errno);
|
||||
|
||||
if (fd == -1 && get_opt_bool("protocol.file.try_encoding_extensions", NULL)) {
|
||||
encoding = try_encoding_extensions(filename, &fd);
|
||||
@ -323,7 +323,7 @@ read_encoded_file(struct string *filename, struct string *page)
|
||||
/* Do all the necessary checks before trying to read the file.
|
||||
* @state code is used to block further progress. */
|
||||
if (fstat(fd, &stt)) {
|
||||
state = -errno;
|
||||
state = connection_state_for_errno(errno);
|
||||
|
||||
} else if (!S_ISREG(stt.st_mode) && encoding != ENCODING_NONE) {
|
||||
/* We only want to open regular encoded files. */
|
||||
@ -331,10 +331,10 @@ read_encoded_file(struct string *filename, struct string *page)
|
||||
|
||||
} else if (!S_ISREG(stt.st_mode) && !is_stdin_pipe(&stt, filename)
|
||||
&& !get_opt_bool("protocol.file.allow_special_files", NULL)) {
|
||||
state = S_FILE_TYPE;
|
||||
state = connection_state(S_FILE_TYPE);
|
||||
|
||||
} else if (!(stream = open_encoded(fd, encoding))) {
|
||||
state = S_OUT_OF_MEM;
|
||||
state = connection_state(S_OUT_OF_MEM);
|
||||
|
||||
} else {
|
||||
int readsize = (int) stt.st_size;
|
||||
@ -343,9 +343,9 @@ read_encoded_file(struct string *filename, struct string *page)
|
||||
/* FIXME: See bug 497 for info about support for big files. */
|
||||
if (readsize != stt.st_size || readsize < 0) {
|
||||
#ifdef EFBIG
|
||||
state = (enum connection_state) -(EFBIG);
|
||||
state = connection_state_for_errno(EFBIG);
|
||||
#else
|
||||
state = S_FILE_ERROR;
|
||||
state = connection_state(S_FILE_ERROR);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
|
@ -39,10 +39,10 @@ enum stream_encoding guess_encoding(unsigned char *filename);
|
||||
const unsigned char *get_encoding_name(enum stream_encoding encoding);
|
||||
|
||||
/* Read from open @stream into the @page string */
|
||||
enum connection_state
|
||||
struct connection_state
|
||||
read_file(struct stream_encoded *stream, int readsize, struct string *page);
|
||||
|
||||
/* Reads the file with the given @filename into the string @source. */
|
||||
enum connection_state read_encoded_file(struct string *filename, struct string *source);
|
||||
struct connection_state read_encoded_file(struct string *filename, struct string *source);
|
||||
|
||||
#endif
|
||||
|
@ -228,28 +228,28 @@ check_queue_bugs(void)
|
||||
#endif
|
||||
|
||||
static void
|
||||
set_connection_socket_state(struct socket *socket, enum connection_state state)
|
||||
set_connection_socket_state(struct socket *socket, struct connection_state state)
|
||||
{
|
||||
assert(socket);
|
||||
set_connection_state(socket->conn, state);
|
||||
}
|
||||
|
||||
static void
|
||||
set_connection_socket_timeout(struct socket *socket, enum connection_state state)
|
||||
set_connection_socket_timeout(struct socket *socket, struct connection_state state)
|
||||
{
|
||||
assert(socket);
|
||||
set_connection_timeout(socket->conn);
|
||||
}
|
||||
|
||||
static void
|
||||
retry_connection_socket(struct socket *socket, enum connection_state state)
|
||||
retry_connection_socket(struct socket *socket, struct connection_state state)
|
||||
{
|
||||
assert(socket);
|
||||
retry_connection(socket->conn, state);
|
||||
}
|
||||
|
||||
static void
|
||||
done_connection_socket(struct socket *socket, enum connection_state state)
|
||||
done_connection_socket(struct socket *socket, struct connection_state state)
|
||||
{
|
||||
assert(socket);
|
||||
abort_connection(socket->conn, state);
|
||||
@ -350,7 +350,7 @@ upload_stat_timer(struct connection *conn)
|
||||
}
|
||||
|
||||
void
|
||||
set_connection_state(struct connection *conn, enum connection_state state)
|
||||
set_connection_state(struct connection *conn, struct connection_state state)
|
||||
{
|
||||
struct download *download;
|
||||
struct progress *progress = conn->progress;
|
||||
@ -360,7 +360,7 @@ set_connection_state(struct connection *conn, enum connection_state state)
|
||||
conn->prev_error = conn->state;
|
||||
|
||||
conn->state = state;
|
||||
if (conn->state == S_TRANS) {
|
||||
if (is_in_state(conn->state, S_TRANS)) {
|
||||
if (upload_progress && upload_progress->timer == TIMER_ID_UNDEF) {
|
||||
start_update_progress(upload_progress,
|
||||
(void (*)(void *)) upload_stat_timer, conn);
|
||||
@ -442,14 +442,14 @@ free_connection_data(struct connection *conn)
|
||||
|
||||
kill_timer(&conn->timer);
|
||||
|
||||
if (conn->state != S_WAIT)
|
||||
if (!is_in_state(conn->state, S_WAIT))
|
||||
done_host_connection(conn);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_connection_callbacks(struct connection *conn)
|
||||
{
|
||||
enum connection_state state = conn->state;
|
||||
struct connection_state state = conn->state;
|
||||
struct download *download, *next;
|
||||
|
||||
foreachsafe (download, next, conn->downloads) {
|
||||
@ -469,7 +469,7 @@ done_connection(struct connection *conn)
|
||||
* connection is in a result state. If it is not already it is an
|
||||
* internal bug. This should never happen but it does. ;) --jonas */
|
||||
if (!is_in_result_state(conn->state))
|
||||
set_connection_state(conn, S_INTERNAL);
|
||||
set_connection_state(conn, connection_state(S_INTERNAL));
|
||||
|
||||
del_from_list(conn);
|
||||
notify_connection_callbacks(conn);
|
||||
@ -728,7 +728,7 @@ static inline void
|
||||
suspend_connection(struct connection *conn)
|
||||
{
|
||||
interrupt_connection(conn);
|
||||
set_connection_state(conn, S_WAIT);
|
||||
set_connection_state(conn, connection_state(S_WAIT));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -742,7 +742,7 @@ run_connection(struct connection *conn)
|
||||
if_assert_failed return;
|
||||
|
||||
if (!add_host_connection(conn)) {
|
||||
set_connection_state(conn, S_OUT_OF_MEM);
|
||||
set_connection_state(conn, connection_state(S_OUT_OF_MEM));
|
||||
done_connection(conn);
|
||||
return;
|
||||
}
|
||||
@ -755,12 +755,12 @@ run_connection(struct connection *conn)
|
||||
|
||||
/* Set certain state on a connection and then abort the connection. */
|
||||
void
|
||||
abort_connection(struct connection *conn, enum connection_state state)
|
||||
abort_connection(struct connection *conn, struct connection_state state)
|
||||
{
|
||||
assertm(is_in_result_state(state),
|
||||
"connection didn't end in result state (%d)", state);
|
||||
|
||||
if (state == S_OK && conn->cached)
|
||||
if (is_in_state(state, S_OK) && conn->cached)
|
||||
normalize_cache_entry(conn->cached, conn->from);
|
||||
|
||||
set_connection_state(conn, state);
|
||||
@ -772,7 +772,7 @@ abort_connection(struct connection *conn, enum connection_state state)
|
||||
|
||||
/* Set certain state on a connection and then retry the connection. */
|
||||
void
|
||||
retry_connection(struct connection *conn, enum connection_state state)
|
||||
retry_connection(struct connection *conn, struct connection_state state)
|
||||
{
|
||||
int max_tries = get_opt_int("connection.retries", NULL);
|
||||
|
||||
@ -799,7 +799,7 @@ try_to_suspend_connection(struct connection *conn, struct uri *uri)
|
||||
|
||||
foreachback (c, connection_queue) {
|
||||
if (get_priority(c) <= priority) return -1;
|
||||
if (c->state == S_WAIT) continue;
|
||||
if (is_in_state(c->state, S_WAIT)) continue;
|
||||
if (c->uri->post && get_priority(c) < PRI_CANCEL) continue;
|
||||
if (uri && !compare_uri(uri, c->uri, URI_HOST)) continue;
|
||||
suspend_connection(c);
|
||||
@ -844,7 +844,8 @@ again:
|
||||
struct connection *cc = c;
|
||||
|
||||
c = c->next;
|
||||
if (cc->state == S_WAIT && get_keepalive_connection(cc)
|
||||
if (is_in_state(cc->state, S_WAIT)
|
||||
&& get_keepalive_connection(cc)
|
||||
&& try_connection(cc, max_conns_to_host, max_conns))
|
||||
goto again;
|
||||
}
|
||||
@ -853,7 +854,7 @@ again:
|
||||
struct connection *cc = c;
|
||||
|
||||
c = c->next;
|
||||
if (cc->state == S_WAIT
|
||||
if (is_in_state(cc->state, S_WAIT)
|
||||
&& try_connection(cc, max_conns_to_host, max_conns))
|
||||
goto again;
|
||||
}
|
||||
@ -863,8 +864,8 @@ again:
|
||||
again2:
|
||||
foreachback (conn, connection_queue) {
|
||||
if (get_priority(conn) < PRI_CANCEL) break;
|
||||
if (conn->state == S_WAIT) {
|
||||
set_connection_state(conn, S_INTERRUPTED);
|
||||
if (is_in_state(conn->state, S_WAIT)) {
|
||||
set_connection_state(conn, connection_state(S_INTERRUPTED));
|
||||
done_connection(conn);
|
||||
goto again2;
|
||||
}
|
||||
@ -886,14 +887,14 @@ load_uri(struct uri *uri, struct uri *referrer, struct download *download,
|
||||
struct cache_entry *cached;
|
||||
struct connection *conn;
|
||||
struct uri *proxy_uri, *proxied_uri;
|
||||
enum connection_state connection_state = S_OK;
|
||||
struct connection_state error_state = connection_state(S_OK);
|
||||
|
||||
if (download) {
|
||||
download->conn = NULL;
|
||||
download->cached = NULL;
|
||||
download->pri = pri;
|
||||
download->state = S_OUT_OF_MEM;
|
||||
download->prev_error = 0;
|
||||
download->state = connection_state(S_OUT_OF_MEM);
|
||||
download->prev_error = connection_state(0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG
|
||||
@ -903,7 +904,7 @@ load_uri(struct uri *uri, struct uri *referrer, struct download *download,
|
||||
foreach (assigned, conn->downloads) {
|
||||
assertm(assigned != download, "Download assigned to '%s'", struri(conn->uri));
|
||||
if_assert_failed {
|
||||
download->state = S_INTERNAL;
|
||||
download->state = connection_state(S_INTERNAL);
|
||||
if (download->callback)
|
||||
download->callback(download, download->data);
|
||||
return 0;
|
||||
@ -917,7 +918,7 @@ load_uri(struct uri *uri, struct uri *referrer, struct download *download,
|
||||
if (cached) {
|
||||
if (download) {
|
||||
download->cached = cached;
|
||||
download->state = S_OK;
|
||||
download->state = connection_state(S_OK);
|
||||
/* XXX:
|
||||
* This doesn't work since sometimes |download->progress|
|
||||
* is undefined and contains random memory locations.
|
||||
@ -934,7 +935,7 @@ load_uri(struct uri *uri, struct uri *referrer, struct download *download,
|
||||
}
|
||||
|
||||
proxied_uri = get_proxied_uri(uri);
|
||||
proxy_uri = get_proxy_uri(uri, &connection_state);
|
||||
proxy_uri = get_proxy_uri(uri, &error_state);
|
||||
|
||||
if (!proxy_uri
|
||||
|| !proxied_uri
|
||||
@ -942,12 +943,13 @@ load_uri(struct uri *uri, struct uri *referrer, struct download *download,
|
||||
&& !proxy_uri->hostlen)) {
|
||||
|
||||
if (download) {
|
||||
if (connection_state == S_OK) {
|
||||
connection_state = proxy_uri && proxied_uri
|
||||
? S_BAD_URL : S_OUT_OF_MEM;
|
||||
if (is_in_state(error_state, S_OK)) {
|
||||
error_state = proxy_uri && proxied_uri
|
||||
? connection_state(S_BAD_URL)
|
||||
: connection_state(S_OUT_OF_MEM);
|
||||
}
|
||||
|
||||
download->state = connection_state;
|
||||
download->state = error_state;
|
||||
download->callback(download, download->data);
|
||||
}
|
||||
if (proxy_uri) done_uri(proxy_uri);
|
||||
@ -987,7 +989,7 @@ load_uri(struct uri *uri, struct uri *referrer, struct download *download,
|
||||
conn = init_connection(proxy_uri, proxied_uri, referrer, start, cache_mode, pri);
|
||||
if (!conn) {
|
||||
if (download) {
|
||||
download->state = S_OUT_OF_MEM;
|
||||
download->state = connection_state(S_OUT_OF_MEM);
|
||||
download->callback(download, download->data);
|
||||
}
|
||||
if (proxy_uri) done_uri(proxy_uri);
|
||||
@ -1003,12 +1005,12 @@ load_uri(struct uri *uri, struct uri *referrer, struct download *download,
|
||||
download->progress = conn->progress;
|
||||
download->conn = conn;
|
||||
download->cached = NULL;
|
||||
download->state = S_OK;
|
||||
download->state = connection_state(S_OK);
|
||||
add_to_list(conn->downloads, download);
|
||||
}
|
||||
|
||||
add_to_queue(conn);
|
||||
set_connection_state(conn, S_WAIT);
|
||||
set_connection_state(conn, connection_state(S_WAIT));
|
||||
|
||||
check_queue_bugs();
|
||||
|
||||
@ -1034,7 +1036,7 @@ cancel_download(struct download *download, int interrupt)
|
||||
|
||||
check_queue_bugs();
|
||||
|
||||
download->state = S_INTERRUPTED;
|
||||
download->state = connection_state(S_INTERRUPTED);
|
||||
del_from_list(download);
|
||||
|
||||
conn = download->conn;
|
||||
@ -1048,7 +1050,7 @@ cancel_download(struct download *download, int interrupt)
|
||||
conn->pri[PRI_CANCEL]++;
|
||||
|
||||
if (conn->detached || interrupt)
|
||||
abort_connection(conn, S_INTERRUPTED);
|
||||
abort_connection(conn, connection_state(S_INTERRUPTED));
|
||||
}
|
||||
|
||||
sort_queue();
|
||||
@ -1197,7 +1199,8 @@ void
|
||||
abort_all_connections(void)
|
||||
{
|
||||
while (!list_empty(connection_queue)) {
|
||||
abort_connection(connection_queue.next, S_INTERRUPTED);
|
||||
abort_connection(connection_queue.next,
|
||||
connection_state(S_INTERRUPTED));
|
||||
}
|
||||
|
||||
abort_all_keepalive_connections();
|
||||
@ -1210,7 +1213,7 @@ abort_background_connections(void)
|
||||
|
||||
foreachsafe (conn, next, connection_queue) {
|
||||
if (get_priority(conn) >= PRI_CANCEL)
|
||||
abort_connection(conn, S_INTERRUPTED);
|
||||
abort_connection(conn, connection_state(S_INTERRUPTED));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,8 +49,8 @@ struct connection {
|
||||
|
||||
unsigned int id;
|
||||
|
||||
enum connection_state state;
|
||||
enum connection_state prev_error;
|
||||
struct connection_state state;
|
||||
struct connection_state prev_error;
|
||||
|
||||
/* The communication socket with the other side. */
|
||||
struct socket *socket;
|
||||
@ -90,14 +90,14 @@ int get_keepalive_connections_count(void);
|
||||
int get_connections_connecting_count(void);
|
||||
int get_connections_transfering_count(void);
|
||||
|
||||
void set_connection_state(struct connection *, enum connection_state);
|
||||
void set_connection_state(struct connection *, struct connection_state);
|
||||
|
||||
int has_keepalive_connection(struct connection *);
|
||||
void add_keepalive_connection(struct connection *conn, long timeout_in_seconds,
|
||||
void (*done)(struct connection *));
|
||||
|
||||
void abort_connection(struct connection *, enum connection_state);
|
||||
void retry_connection(struct connection *, enum connection_state);
|
||||
void abort_connection(struct connection *, struct connection_state);
|
||||
void retry_connection(struct connection *, struct connection_state);
|
||||
|
||||
void cancel_download(struct download *download, int interrupt);
|
||||
void move_download(struct download *old, struct download *new,
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include "network/ssl/socket.h"
|
||||
#include "osdep/osdep.h"
|
||||
#include "osdep/getifaddrs.h"
|
||||
#include "protocol/http/blacklist.h"
|
||||
#include "protocol/protocol.h"
|
||||
#include "protocol/uri.h"
|
||||
#include "util/error.h"
|
||||
@ -65,6 +66,7 @@ struct connect_info {
|
||||
void *dnsquery; /* Pointer to DNS query info. */
|
||||
int port; /* Which port to bind to. */
|
||||
int ip_family; /* If non-zero, force to IP version. */
|
||||
struct uri *uri; /* For updating the blacklist. */
|
||||
};
|
||||
|
||||
|
||||
@ -104,6 +106,7 @@ init_connection_info(struct uri *uri, struct socket *socket,
|
||||
connect_info->ip_family = uri->ip_family;
|
||||
connect_info->triedno = -1;
|
||||
connect_info->addr = NULL;
|
||||
connect_info->uri = get_uri_reference(uri);
|
||||
|
||||
return connect_info;
|
||||
}
|
||||
@ -118,6 +121,7 @@ done_connection_info(struct socket *socket)
|
||||
if (connect_info->dnsquery) kill_dns_request(&connect_info->dnsquery);
|
||||
|
||||
mem_free_if(connect_info->addr);
|
||||
done_uri(connect_info->uri);
|
||||
mem_free_set(&socket->connect_info, NULL);
|
||||
}
|
||||
|
||||
@ -163,13 +167,13 @@ close_socket(struct socket *socket)
|
||||
void
|
||||
dns_exception(struct socket *socket)
|
||||
{
|
||||
connect_socket(socket, S_EXCEPT);
|
||||
connect_socket(socket, connection_state(S_EXCEPT));
|
||||
}
|
||||
|
||||
static void
|
||||
exception(struct socket *socket)
|
||||
{
|
||||
socket->ops->retry(socket, S_EXCEPT);
|
||||
socket->ops->retry(socket, connection_state(S_EXCEPT));
|
||||
}
|
||||
|
||||
|
||||
@ -177,23 +181,23 @@ void
|
||||
timeout_socket(struct socket *socket)
|
||||
{
|
||||
if (!socket->connect_info) {
|
||||
socket->ops->retry(socket, S_TIMEOUT);
|
||||
socket->ops->retry(socket, connection_state(S_TIMEOUT));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Is the DNS resolving still in progress? */
|
||||
if (socket->connect_info->dnsquery) {
|
||||
socket->ops->done(socket, S_TIMEOUT);
|
||||
socket->ops->done(socket, connection_state(S_TIMEOUT));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try the next address, */
|
||||
connect_socket(socket, S_TIMEOUT);
|
||||
connect_socket(socket, connection_state(S_TIMEOUT));
|
||||
|
||||
/* Reset the timeout if connect_socket() started a new attempt
|
||||
* to connect. */
|
||||
if (socket->connect_info)
|
||||
socket->ops->set_timeout(socket, 0);
|
||||
socket->ops->set_timeout(socket, connection_state(0));
|
||||
}
|
||||
|
||||
|
||||
@ -205,7 +209,7 @@ dns_found(struct socket *socket, struct sockaddr_storage *addr, int addrlen)
|
||||
int size;
|
||||
|
||||
if (!addr) {
|
||||
socket->ops->done(socket, S_NO_DNS);
|
||||
socket->ops->done(socket, connection_state(S_NO_DNS));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -215,7 +219,7 @@ dns_found(struct socket *socket, struct sockaddr_storage *addr, int addrlen)
|
||||
|
||||
connect_info->addr = mem_alloc(size);
|
||||
if (!connect_info->addr) {
|
||||
socket->ops->done(socket, S_OUT_OF_MEM);
|
||||
socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -229,7 +233,7 @@ dns_found(struct socket *socket, struct sockaddr_storage *addr, int addrlen)
|
||||
* problem if connect_socket() fails without doing any system calls
|
||||
* which is only the case when forcing the IP family. So it is better to
|
||||
* handle it in connect_socket(). */
|
||||
connect_socket(socket, S_CONN);
|
||||
connect_socket(socket, connection_state(S_CONN));
|
||||
}
|
||||
|
||||
void
|
||||
@ -240,17 +244,17 @@ make_connection(struct socket *socket, struct uri *uri,
|
||||
struct connect_info *connect_info;
|
||||
enum dns_result result;
|
||||
|
||||
socket->ops->set_timeout(socket, 0);
|
||||
socket->ops->set_timeout(socket, connection_state(0));
|
||||
|
||||
if (!host) {
|
||||
socket->ops->retry(socket, S_OUT_OF_MEM);
|
||||
socket->ops->retry(socket, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
connect_info = init_connection_info(uri, socket, connect_done);
|
||||
if (!connect_info) {
|
||||
mem_free(host);
|
||||
socket->ops->retry(socket, S_OUT_OF_MEM);
|
||||
socket->ops->retry(socket, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -258,6 +262,11 @@ make_connection(struct socket *socket, struct uri *uri,
|
||||
/* XXX: Keep here and not in init_connection_info() to make
|
||||
* complete_connect_socket() work from the HTTP implementation. */
|
||||
socket->need_ssl = get_protocol_need_ssl(uri->protocol);
|
||||
if (!socket->set_no_tls) {
|
||||
enum blacklist_flags flags = get_blacklist_flags(uri);
|
||||
socket->no_tls = ((flags & SERVER_BLACKLIST_NO_TLS) != 0);
|
||||
socket->set_no_tls = 1;
|
||||
}
|
||||
|
||||
debug_transfer_log("\nCONNECTION: ", -1);
|
||||
debug_transfer_log(host, -1);
|
||||
@ -269,7 +278,7 @@ make_connection(struct socket *socket, struct uri *uri,
|
||||
mem_free(host);
|
||||
|
||||
if (result == DNS_ASYNC)
|
||||
socket->ops->set_state(socket, S_DNS);
|
||||
socket->ops->set_state(socket, connection_state(S_DNS));
|
||||
}
|
||||
|
||||
|
||||
@ -307,7 +316,8 @@ get_pasv_socket(struct socket *ctrl_socket, struct sockaddr_storage *addr)
|
||||
if (getsockname(ctrl_socket->fd, pasv_addr, &len)) {
|
||||
sock_error:
|
||||
if (sock != -1) close(sock);
|
||||
ctrl_socket->ops->retry(ctrl_socket, -errno);
|
||||
ctrl_socket->ops->retry(ctrl_socket,
|
||||
connection_state_for_errno(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -425,13 +435,27 @@ complete_connect_socket(struct socket *socket, struct uri *uri,
|
||||
{
|
||||
struct connect_info *connect_info = socket->connect_info;
|
||||
|
||||
if (connect_info && connect_info->uri) {
|
||||
/* Remember whether the server supported TLS or not.
|
||||
* Then the next request can immediately use the right
|
||||
* protocol. This is important for HTTP POST requests
|
||||
* because it is not safe to silently retry them. The
|
||||
* uri parameter is normally NULL here so don't use it. */
|
||||
if (socket->no_tls)
|
||||
add_blacklist_entry(connect_info->uri,
|
||||
SERVER_BLACKLIST_NO_TLS);
|
||||
else
|
||||
del_blacklist_entry(connect_info->uri,
|
||||
SERVER_BLACKLIST_NO_TLS);
|
||||
}
|
||||
|
||||
/* This is a special case used by the HTTP implementation to acquire an
|
||||
* SSL link for handling CONNECT requests. */
|
||||
if (!connect_info) {
|
||||
assert(uri && socket);
|
||||
connect_info = init_connection_info(uri, socket, done);
|
||||
if (!connect_info) {
|
||||
socket->ops->done(socket, S_OUT_OF_MEM);
|
||||
socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -459,6 +483,7 @@ static void
|
||||
connected(struct socket *socket)
|
||||
{
|
||||
int err = 0;
|
||||
struct connection_state state = connection_state(0);
|
||||
socklen_t len = sizeof(err);
|
||||
|
||||
assertm(socket->connect_info != NULL, "Lost connect_info!");
|
||||
@ -467,17 +492,21 @@ connected(struct socket *socket)
|
||||
if (getsockopt(socket->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len) == 0) {
|
||||
/* Why does EMX return so large values? */
|
||||
if (err >= 10000) err -= 10000;
|
||||
if (err != 0)
|
||||
state = connection_state_for_errno(err);
|
||||
else
|
||||
state = connection_state(0);
|
||||
} else {
|
||||
/* getsockopt() failed */
|
||||
if (errno > 0)
|
||||
err = errno;
|
||||
if (errno != 0)
|
||||
state = connection_state_for_errno(errno);
|
||||
else
|
||||
err = -(S_STATE);
|
||||
state = connection_state(S_STATE);
|
||||
}
|
||||
|
||||
if (err > 0) {
|
||||
if (!is_in_state(state, 0)) {
|
||||
/* There are maybe still some more candidates. */
|
||||
connect_socket(socket, -err);
|
||||
connect_socket(socket, state);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -485,7 +514,7 @@ connected(struct socket *socket)
|
||||
}
|
||||
|
||||
void
|
||||
connect_socket(struct socket *csocket, enum connection_state state)
|
||||
connect_socket(struct socket *csocket, struct connection_state state)
|
||||
{
|
||||
int sock = -1;
|
||||
struct connect_info *connect_info = csocket->connect_info;
|
||||
@ -617,7 +646,7 @@ connect_socket(struct socket *csocket, enum connection_state state)
|
||||
/* It will take some more time... */
|
||||
set_handlers(sock, NULL, (select_handler_T) connected,
|
||||
(select_handler_T) dns_exception, csocket);
|
||||
csocket->ops->set_state(csocket, S_CONN);
|
||||
csocket->ops->set_state(csocket, connection_state(S_CONN));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -635,7 +664,7 @@ connect_socket(struct socket *csocket, enum connection_state state)
|
||||
* what matters is the last one because we do not know the
|
||||
* previous one's errno, and the added complexity wouldn't
|
||||
* really be worth it. */
|
||||
csocket->ops->done(csocket, S_LOCAL_ONLY);
|
||||
csocket->ops->done(csocket, connection_state(S_LOCAL_ONLY));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -643,10 +672,10 @@ connect_socket(struct socket *csocket, enum connection_state state)
|
||||
* new. Else use the S_DNS _progress_ state to make sure that no
|
||||
* download callbacks will report any errors. */
|
||||
if (trno != connect_info->triedno && !silent_fail)
|
||||
state = -errno;
|
||||
state = connection_state_for_errno(errno);
|
||||
else if (trno == -1 && silent_fail)
|
||||
/* All failed. */
|
||||
state = S_NO_FORCED_DNS;
|
||||
state = connection_state(S_NO_FORCED_DNS);
|
||||
|
||||
csocket->ops->retry(csocket, state);
|
||||
}
|
||||
@ -681,14 +710,14 @@ write_select(struct socket *socket)
|
||||
|
||||
assertm(wb != NULL, "write socket has no buffer");
|
||||
if_assert_failed {
|
||||
socket->ops->done(socket, S_INTERNAL);
|
||||
socket->ops->done(socket, connection_state(S_INTERNAL));
|
||||
return;
|
||||
}
|
||||
|
||||
/* We are making some progress, therefore reset the timeout; ie. when
|
||||
* uploading large files the time needed for all the data to be sent can
|
||||
* easily exceed the timeout. */
|
||||
socket->ops->set_timeout(socket, 0);
|
||||
socket->ops->set_timeout(socket, connection_state(0));
|
||||
|
||||
#if 0
|
||||
printf("ws: %d\n",wb->length-wb->pos);
|
||||
@ -708,17 +737,17 @@ write_select(struct socket *socket)
|
||||
|
||||
switch (wr) {
|
||||
case SOCKET_CANT_WRITE:
|
||||
socket->ops->retry(socket, S_CANT_WRITE);
|
||||
socket->ops->retry(socket, connection_state(S_CANT_WRITE));
|
||||
break;
|
||||
|
||||
case SOCKET_SYSCALL_ERROR:
|
||||
socket->ops->retry(socket, -errno);
|
||||
socket->ops->retry(socket, connection_state_for_errno(errno));
|
||||
break;
|
||||
|
||||
case SOCKET_INTERNAL_ERROR:
|
||||
/* The global errno variable is used for passing
|
||||
* internal connection_state error value. */
|
||||
socket->ops->done(socket, -errno);
|
||||
socket->ops->done(socket, connection_state(errno));
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -754,7 +783,7 @@ write_select(struct socket *socket)
|
||||
|
||||
void
|
||||
write_to_socket(struct socket *socket, unsigned char *data, int len,
|
||||
enum connection_state state, socket_write_T write_done)
|
||||
struct connection_state state, socket_write_T write_done)
|
||||
{
|
||||
select_handler_T read_handler;
|
||||
struct write_buffer *wb;
|
||||
@ -764,11 +793,11 @@ write_to_socket(struct socket *socket, unsigned char *data, int len,
|
||||
assert(len > 0);
|
||||
if_assert_failed return;
|
||||
|
||||
socket->ops->set_timeout(socket, 0);
|
||||
socket->ops->set_timeout(socket, connection_state(0));
|
||||
|
||||
wb = mem_alloc(sizeof(*wb) + len);
|
||||
if (!wb) {
|
||||
socket->ops->done(socket, S_OUT_OF_MEM);
|
||||
socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -811,14 +840,14 @@ read_select(struct socket *socket)
|
||||
|
||||
assertm(rb != NULL, "read socket has no buffer");
|
||||
if_assert_failed {
|
||||
socket->ops->done(socket, S_INTERNAL);
|
||||
socket->ops->done(socket, connection_state(S_INTERNAL));
|
||||
return;
|
||||
}
|
||||
|
||||
/* We are making some progress, therefore reset the timeout; we do this
|
||||
* for read_select() to avoid that the periodic calls to user handlers
|
||||
* has to do it. */
|
||||
socket->ops->set_timeout(socket, 0);
|
||||
socket->ops->set_timeout(socket, connection_state(0));
|
||||
|
||||
if (!socket->duplex)
|
||||
clear_handlers(socket->fd);
|
||||
@ -828,7 +857,7 @@ read_select(struct socket *socket)
|
||||
|
||||
rb = mem_realloc(rb, size);
|
||||
if (!rb) {
|
||||
socket->ops->done(socket, S_OUT_OF_MEM);
|
||||
socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
rb->freespace = size - sizeof(*rb) - rb->length;
|
||||
@ -848,7 +877,7 @@ read_select(struct socket *socket)
|
||||
switch (rd) {
|
||||
#ifdef CONFIG_SSL
|
||||
case SOCKET_SSL_WANT_READ:
|
||||
read_from_socket(socket, rb, S_TRANS, rb->done);
|
||||
read_from_socket(socket, rb, connection_state(S_TRANS), rb->done);
|
||||
break;
|
||||
#endif
|
||||
case SOCKET_CANT_READ:
|
||||
@ -858,15 +887,17 @@ read_select(struct socket *socket)
|
||||
break;
|
||||
}
|
||||
|
||||
errno = -S_CANT_READ;
|
||||
/* Fall-through */
|
||||
socket->ops->retry(socket, connection_state(S_CANT_READ));
|
||||
break;
|
||||
|
||||
case SOCKET_SYSCALL_ERROR:
|
||||
socket->ops->retry(socket, -errno);
|
||||
socket->ops->retry(socket, connection_state_for_errno(errno));
|
||||
break;
|
||||
|
||||
case SOCKET_INTERNAL_ERROR:
|
||||
socket->ops->done(socket, -errno);
|
||||
/* The global errno variable is used for passing
|
||||
* internal connection_state error value. */
|
||||
socket->ops->done(socket, connection_state(errno));
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -887,7 +918,7 @@ alloc_read_buffer(struct socket *socket)
|
||||
|
||||
rb = mem_calloc(1, RD_SIZE(rb, 0));
|
||||
if (!rb) {
|
||||
socket->ops->done(socket, S_OUT_OF_MEM);
|
||||
socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -902,13 +933,13 @@ alloc_read_buffer(struct socket *socket)
|
||||
|
||||
void
|
||||
read_from_socket(struct socket *socket, struct read_buffer *buffer,
|
||||
enum connection_state state, socket_read_T done)
|
||||
struct connection_state state, socket_read_T done)
|
||||
{
|
||||
select_handler_T write_handler;
|
||||
|
||||
buffer->done = done;
|
||||
|
||||
socket->ops->set_timeout(socket, 0);
|
||||
socket->ops->set_timeout(socket, connection_state(0));
|
||||
socket->ops->set_state(socket, state);
|
||||
|
||||
if (socket->read_buffer && buffer != socket->read_buffer)
|
||||
@ -930,12 +961,13 @@ read_response_from_socket(struct socket *socket)
|
||||
{
|
||||
struct read_buffer *rb = alloc_read_buffer(socket);
|
||||
|
||||
if (rb) read_from_socket(socket, rb, S_SENT, socket->read_done);
|
||||
if (rb) read_from_socket(socket, rb, connection_state(S_SENT),
|
||||
socket->read_done);
|
||||
}
|
||||
|
||||
void
|
||||
request_from_socket(struct socket *socket, unsigned char *data, int datalen,
|
||||
enum connection_state state, enum socket_state sock_state,
|
||||
struct connection_state state, enum socket_state sock_state,
|
||||
socket_read_T read_done)
|
||||
{
|
||||
socket->read_done = read_done;
|
||||
|
@ -16,8 +16,8 @@ struct uri;
|
||||
|
||||
/* Use internally for error return values. */
|
||||
enum socket_error {
|
||||
SOCKET_SYSCALL_ERROR = -1, /* Retry with -errno state. */
|
||||
SOCKET_INTERNAL_ERROR = -2, /* Stop with -errno state. */
|
||||
SOCKET_SYSCALL_ERROR = -1, /* Retry with connection_state_for_errno(errno). */
|
||||
SOCKET_INTERNAL_ERROR = -2, /* Stop with connection_state(errno). */
|
||||
SOCKET_SSL_WANT_READ = -3, /* Try to read some more. */
|
||||
SOCKET_CANT_READ = -4, /* Retry with S_CANT_READ state. */
|
||||
SOCKET_CANT_WRITE = -5, /* Retry with S_CANT_WRITE state. */
|
||||
@ -39,7 +39,7 @@ enum socket_state {
|
||||
typedef void (*socket_read_T)(struct socket *, struct read_buffer *);
|
||||
typedef void (*socket_write_T)(struct socket *);
|
||||
typedef void (*socket_connect_T)(struct socket *);
|
||||
typedef void (*socket_operation_T)(struct socket *, enum connection_state state);
|
||||
typedef void (*socket_operation_T)(struct socket *, struct connection_state);
|
||||
|
||||
struct socket_operations {
|
||||
/* Report change in the state of the socket. */
|
||||
@ -97,6 +97,7 @@ struct socket {
|
||||
unsigned int protocol_family:1; /* EL_PF_INET, EL_PF_INET6 */
|
||||
unsigned int need_ssl:1; /* If the socket needs SSL support */
|
||||
unsigned int no_tls:1; /* Internal SSL flag. */
|
||||
unsigned int set_no_tls:1; /* Was the blacklist checked yet? */
|
||||
unsigned int duplex:1; /* Allow simultaneous reads & writes. */
|
||||
};
|
||||
|
||||
@ -139,7 +140,7 @@ int get_pasv_socket(struct socket *ctrl_socket, struct sockaddr_storage *addr);
|
||||
/* Try to connect to the next available address or force the connection to retry
|
||||
* if all has already been tried. Updates the connection state to
|
||||
* @connection_state. */
|
||||
void connect_socket(struct socket *socket, enum connection_state state);
|
||||
void connect_socket(struct socket *socket, struct connection_state state);
|
||||
|
||||
/* Used by the SSL layer when negotiating. */
|
||||
void dns_exception(struct socket *socket);
|
||||
@ -150,17 +151,17 @@ void dns_exception(struct socket *socket);
|
||||
/* Reads data from @socket into @buffer. Calls @done each time new data is
|
||||
* ready. */
|
||||
void read_from_socket(struct socket *socket, struct read_buffer *buffer,
|
||||
enum connection_state state, socket_read_T done);
|
||||
struct connection_state state, socket_read_T done);
|
||||
|
||||
/* Writes @datalen bytes from @data buffer to the passed @socket. When all data
|
||||
* is written the @done callback will be called. */
|
||||
void write_to_socket(struct socket *socket,
|
||||
unsigned char *data, int datalen,
|
||||
enum connection_state state, socket_write_T write_done);
|
||||
struct connection_state state, socket_write_T write_done);
|
||||
|
||||
/* Send request and get response. */
|
||||
void request_from_socket(struct socket *socket, unsigned char *data, int datalen,
|
||||
enum connection_state state, enum socket_state sock_state,
|
||||
struct connection_state state, enum socket_state sock_state,
|
||||
socket_read_T read_done);
|
||||
|
||||
/* Initialize a read buffer. */
|
||||
|
@ -93,7 +93,7 @@ ssl_want_read(struct socket *socket)
|
||||
#ifdef CONFIG_GNUTLS
|
||||
if (get_opt_bool("connection.ssl.cert_verify", NULL)
|
||||
&& gnutls_certificate_verify_peers(*((ssl_t *) socket->ssl))) {
|
||||
socket->ops->retry(socket, S_SSL_ERROR);
|
||||
socket->ops->retry(socket, connection_state(S_SSL_ERROR));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@ -107,8 +107,8 @@ ssl_want_read(struct socket *socket)
|
||||
break;
|
||||
|
||||
default:
|
||||
socket->no_tls = 1;
|
||||
socket->ops->retry(socket, S_SSL_ERROR);
|
||||
socket->no_tls = !socket->no_tls;
|
||||
socket->ops->retry(socket, connection_state(S_SSL_ERROR));
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,7 +119,7 @@ ssl_connect(struct socket *socket)
|
||||
int ret;
|
||||
|
||||
if (init_ssl_connection(socket) == S_SSL_ERROR) {
|
||||
socket->ops->done(socket, S_SSL_ERROR);
|
||||
socket->ops->done(socket, connection_state(S_SSL_ERROR));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -173,7 +173,7 @@ ssl_connect(struct socket *socket)
|
||||
switch (ret) {
|
||||
case SSL_ERROR_WANT_READ:
|
||||
case SSL_ERROR_WANT_READ2:
|
||||
socket->ops->set_state(socket, S_SSL_NEG);
|
||||
socket->ops->set_state(socket, connection_state(S_SSL_NEG));
|
||||
set_handlers(socket->fd, (select_handler_T) ssl_want_read,
|
||||
NULL, (select_handler_T) dns_exception, socket);
|
||||
return -1;
|
||||
@ -190,17 +190,17 @@ ssl_connect(struct socket *socket)
|
||||
default:
|
||||
if (ret != SSL_ERROR_NONE) {
|
||||
/* DBG("sslerr %s", gnutls_strerror(ret)); */
|
||||
socket->no_tls = 1;
|
||||
socket->no_tls = !socket->no_tls;
|
||||
}
|
||||
|
||||
connect_socket(socket, S_SSL_ERROR);
|
||||
connect_socket(socket, connection_state(S_SSL_ERROR));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return -1 on error, bytes written on success. */
|
||||
/* Return enum socket_error on error, bytes written on success. */
|
||||
ssize_t
|
||||
ssl_write(struct socket *socket, unsigned char *data, int len)
|
||||
{
|
||||
@ -222,15 +222,14 @@ ssl_write(struct socket *socket, unsigned char *data, int len)
|
||||
if (err == SSL_ERROR_SYSCALL)
|
||||
return SOCKET_SYSCALL_ERROR;
|
||||
|
||||
errno = -S_SSL_ERROR;
|
||||
|
||||
errno = S_SSL_ERROR;
|
||||
return SOCKET_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
return wr;
|
||||
}
|
||||
|
||||
/* Return -1 on error, rd or success. */
|
||||
/* Return enum socket_error on error, bytes read on success. */
|
||||
ssize_t
|
||||
ssl_read(struct socket *socket, unsigned char *data, int len)
|
||||
{
|
||||
@ -258,8 +257,7 @@ ssl_read(struct socket *socket, unsigned char *data, int len)
|
||||
if (err == SSL_ERROR_SYSCALL2)
|
||||
return SOCKET_SYSCALL_ERROR;
|
||||
|
||||
errno = -S_SSL_ERROR;
|
||||
|
||||
errno = S_SSL_ERROR;
|
||||
return SOCKET_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#elif defined(CONFIG_GNUTLS)
|
||||
#include <gcrypt.h>
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/x509.h>
|
||||
#else
|
||||
#error "Huh?! You have SSL enabled, but not OPENSSL nor GNUTLS!! And then you want exactly *what* from me?"
|
||||
#endif
|
||||
@ -124,6 +125,8 @@ static void
|
||||
init_gnutls(struct module *module)
|
||||
{
|
||||
int ret = gnutls_global_init();
|
||||
unsigned char *ca_file = get_opt_str("connection.ssl.trusted_ca_file",
|
||||
NULL);
|
||||
|
||||
if (ret < 0)
|
||||
INTERNAL("GNUTLS init failed: %s", gnutls_strerror(ret));
|
||||
@ -137,8 +140,16 @@ init_gnutls(struct module *module)
|
||||
if (ret < 0)
|
||||
INTERNAL("GNUTLS X509 credentials alloc failed: %s",
|
||||
gnutls_strerror(ret));
|
||||
|
||||
/* Here, we should load certificate files etc. */
|
||||
if (*ca_file) {
|
||||
/* FIXME: check returned values. --witekfl */
|
||||
gnutls_certificate_set_x509_trust_file(xcred, ca_file,
|
||||
GNUTLS_X509_FMT_PEM);
|
||||
|
||||
gnutls_certificate_set_verify_flags(xcred,
|
||||
GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
@ -152,8 +163,25 @@ done_gnutls(struct module *module)
|
||||
static struct option_info gnutls_options[] = {
|
||||
INIT_OPT_BOOL("connection.ssl", N_("Verify certificates"),
|
||||
"cert_verify", 0, 0,
|
||||
N_("Verify the peer's SSL certificate. Note that this\n"
|
||||
"probably doesn't work properly at all with GnuTLS.")),
|
||||
N_("Verify the peer's SSL certificate. If you enable\n"
|
||||
"this, set also \"Trusted CA file\".")),
|
||||
|
||||
/* The default value of the following option points to a file
|
||||
* generated by the ca-certificates Debian package. Don't use
|
||||
* CONFDIR here: if someone installs ELinks in $HOME and wants
|
||||
* to have a user-specific trust list, he or she can just
|
||||
* change the file name via the option manager. Distributors
|
||||
* of binary packages should of course change the default to
|
||||
* suit their systems.
|
||||
* TODO: If the file name is relative, look in elinks_home? */
|
||||
INIT_OPT_STRING("connection.ssl", N_("Trusted CA file"),
|
||||
"trusted_ca_file", 0, "/etc/ssl/certs/ca-certificates.crt",
|
||||
N_("The location of a file containing certificates of\n"
|
||||
"trusted certification authorities in PEM format.\n"
|
||||
"ELinks then trusts certificates issued by these CAs.\n"
|
||||
"If you change this option or the file, you must\n"
|
||||
"restart ELinks for the changes to take effect.\n"
|
||||
"This option affects GnuTLS but not OpenSSL.")),
|
||||
|
||||
NULL_OPTION_INFO,
|
||||
};
|
||||
|
@ -127,6 +127,13 @@ static const struct s_msg_dsc msg_dsc[] = {
|
||||
{S_BITTORRENT_BAD_URL, N_("The BitTorrent URL does not point to a valid URL")},
|
||||
#endif
|
||||
|
||||
/* fsp_open_session() failed but did not set errno.
|
||||
* fsp_open_session() never sends anything to the FSP server,
|
||||
* so this error does not mean the server itself does not work.
|
||||
* More likely, there was some problem in asking a DNS server
|
||||
* about the address of the FSP server. */
|
||||
{S_FSP_OPEN_SESSION_UNKN, N_("FSP server not found")},
|
||||
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
@ -143,7 +150,7 @@ static INIT_LIST_OF(struct strerror_val, strerror_buf);
|
||||
* It never returns NULL (if one changes that, be warn that
|
||||
* callers may not test for this condition) --Zas */
|
||||
unsigned char *
|
||||
get_state_message(enum connection_state state, struct terminal *term)
|
||||
get_state_message(struct connection_state state, struct terminal *term)
|
||||
{
|
||||
unsigned char *e;
|
||||
struct strerror_val *s;
|
||||
@ -154,13 +161,13 @@ get_state_message(enum connection_state state, struct terminal *term)
|
||||
int i;
|
||||
|
||||
for (i = 0; msg_dsc[i].msg; i++)
|
||||
if (msg_dsc[i].n == state)
|
||||
if (msg_dsc[i].n == state.basic)
|
||||
return _(msg_dsc[i].msg, term);
|
||||
|
||||
return unknown_error;
|
||||
}
|
||||
|
||||
e = (unsigned char *) strerror(-state);
|
||||
e = (unsigned char *) strerror(state.syserr);
|
||||
if (!e || !*e) return unknown_error;
|
||||
|
||||
len = strlen(e);
|
||||
|
@ -1,6 +1,8 @@
|
||||
#ifndef EL__NETWORK_STATE_H
|
||||
#define EL__NETWORK_STATE_H
|
||||
|
||||
#include "util/error.h" /* assert() */
|
||||
|
||||
struct terminal;
|
||||
|
||||
enum connection_priority {
|
||||
@ -15,23 +17,18 @@ enum connection_priority {
|
||||
PRIORITIES,
|
||||
};
|
||||
|
||||
/* Numbers < 0 and > -100000 are reserved for system errors reported via
|
||||
* errno/strerror(), see session.c and connection.c for further information. */
|
||||
/* WARNING: an errno value <= -100000 may cause some bad things... */
|
||||
/* NOTE: Winsock errors are in range 10000..11004. Hence our abs. values are
|
||||
* above this. */
|
||||
|
||||
#define is_system_error(state) (S_OK < (state) && (state) < S_WAIT)
|
||||
#define is_in_result_state(state) ((state) < 0)
|
||||
#define is_in_progress_state(state) ((state) >= 0)
|
||||
#define is_in_connecting_state(state) (S_WAIT < (state) && (state) < S_TRANS)
|
||||
#define is_in_transfering_state(state) ((state) >= S_TRANS)
|
||||
#define is_in_queued_state(state) (is_in_connecting_state(state) || (state) == S_WAIT)
|
||||
#define is_system_error(state) ((state).basic == S_ERRNO)
|
||||
#define is_in_state(state,basic_) ((state).basic == (basic_))
|
||||
#define is_in_result_state(state) ((state).basic < 0)
|
||||
#define is_in_progress_state(state) ((state).basic >= 0)
|
||||
#define is_in_connecting_state(state) (S_WAIT < (state).basic && (state).basic < S_TRANS)
|
||||
#define is_in_transfering_state(state) ((state).basic >= S_TRANS)
|
||||
#define is_in_queued_state(state) (is_in_connecting_state(state) || (state).basic == S_WAIT)
|
||||
|
||||
/* FIXME: Namespace clash with Windows headers. */
|
||||
#undef S_OK
|
||||
|
||||
enum connection_state {
|
||||
enum connection_basic_state {
|
||||
/* States >= 0 are used for connections still in progress. */
|
||||
S_WAIT = 0,
|
||||
S_DNS,
|
||||
@ -49,6 +46,7 @@ enum connection_state {
|
||||
|
||||
/* State < 0 are used for the final result of a connection
|
||||
* (it's finished already and it ended up like this) */
|
||||
S_ERRNO = -1,
|
||||
S_OK = -100000,
|
||||
S_INTERRUPTED = -100001,
|
||||
S_EXCEPT = -100002,
|
||||
@ -106,9 +104,48 @@ enum connection_state {
|
||||
S_BITTORRENT_METAINFO = -100801,
|
||||
S_BITTORRENT_TRACKER = -100802,
|
||||
S_BITTORRENT_BAD_URL = -100803,
|
||||
|
||||
S_FSP_OPEN_SESSION_UNKN = -100900,
|
||||
};
|
||||
|
||||
unsigned char *get_state_message(enum connection_state state, struct terminal *term);
|
||||
/** Either an ELinks internal status code or an error code from the
|
||||
* system. Use connection_state() or connection_state_for_errno()
|
||||
* to construct objects of this type. */
|
||||
struct connection_state {
|
||||
/** An ELinks internal status code, or ::S_ERRNO if this
|
||||
* structure holds a system error instead. */
|
||||
enum connection_basic_state basic;
|
||||
|
||||
/** When #state is ::S_ERRNO, syserr is the saved value of
|
||||
* errno. Otherwise, syserr should be 0. */
|
||||
int syserr;
|
||||
};
|
||||
|
||||
unsigned char *get_state_message(struct connection_state state, struct terminal *term);
|
||||
void done_state_message(void);
|
||||
|
||||
static inline struct connection_state
|
||||
connection_state(enum connection_basic_state basic)
|
||||
{
|
||||
struct connection_state state = {0};
|
||||
|
||||
assert(basic != S_ERRNO);
|
||||
if_assert_failed basic = S_INTERNAL;
|
||||
|
||||
state.basic = basic;
|
||||
return state;
|
||||
}
|
||||
|
||||
static inline struct connection_state
|
||||
connection_state_for_errno(int syserr)
|
||||
{
|
||||
struct connection_state state = {0};
|
||||
|
||||
/* read_encoded_file() can pass syserr==0 here, so don't
|
||||
* assert otherwise. */
|
||||
state.basic = S_ERRNO;
|
||||
state.syserr = syserr;
|
||||
return state;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -119,5 +119,5 @@ about_protocol_handler(struct connection *conn)
|
||||
}
|
||||
|
||||
conn->cached = cached;
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
}
|
||||
|
@ -294,7 +294,7 @@ add_bittorrent_selection(struct uri *uri, int *selection, size_t size)
|
||||
static INIT_LIST_OF(struct bittorrent_message, bittorrent_messages);
|
||||
|
||||
void
|
||||
add_bittorrent_message(struct uri *uri, enum connection_state state,
|
||||
add_bittorrent_message(struct uri *uri, struct connection_state state,
|
||||
struct bittorrent_const_string *string)
|
||||
{
|
||||
struct bittorrent_message *message;
|
||||
|
@ -16,7 +16,7 @@ uint32_t get_bittorrent_peerwire_max_request_length(void);
|
||||
int *get_bittorrent_selection(struct uri *uri, size_t size);
|
||||
void add_bittorrent_selection(struct uri *uri, int *selection, size_t size);
|
||||
|
||||
void add_bittorrent_message(struct uri *uri, enum connection_state state,
|
||||
void add_bittorrent_message(struct uri *uri, struct connection_state state,
|
||||
struct bittorrent_const_string *);
|
||||
|
||||
#endif
|
||||
|
@ -333,13 +333,14 @@ bittorrent_fetch_callback(struct download *download, void *data)
|
||||
struct cache_entry *cached = download->cached;
|
||||
|
||||
/* If the callback was removed we should shutdown ASAP. */
|
||||
if (!fetcher->callback || download->state == S_INTERRUPTED) {
|
||||
if (download->state == S_INTERRUPTED)
|
||||
if (!fetcher->callback || is_in_state(download->state, S_INTERRUPTED)) {
|
||||
if (is_in_state(download->state, S_INTERRUPTED))
|
||||
mem_free(fetcher);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_in_result_state(download->state) && download->state != S_OK) {
|
||||
if (is_in_result_state(download->state)
|
||||
&& !is_in_state(download->state, S_OK)) {
|
||||
fetcher->callback(fetcher->data, download->state, NULL);
|
||||
if (fetcher->ref)
|
||||
*fetcher->ref = NULL;
|
||||
@ -353,7 +354,7 @@ bittorrent_fetch_callback(struct download *download, void *data)
|
||||
if (cached->redirect && fetcher->redirects++ < MAX_REDIRECTS) {
|
||||
cancel_download(download, 0);
|
||||
|
||||
download->state = S_WAIT_REDIR;
|
||||
download->state = connection_state(S_WAIT_REDIR);
|
||||
|
||||
load_uri(cached->redirect, cached->uri, download,
|
||||
PRI_DOWNLOAD, CACHE_MODE_NORMAL,
|
||||
@ -365,13 +366,13 @@ bittorrent_fetch_callback(struct download *download, void *data)
|
||||
if (is_in_progress_state(download->state))
|
||||
return;
|
||||
|
||||
assert(download->state == S_OK);
|
||||
assert(is_in_state(download->state, S_OK));
|
||||
|
||||
/* If the entry is chunked defragment it and grab the single, remaining
|
||||
* fragment. */
|
||||
fragment = get_cache_fragment(cached);
|
||||
if (!fragment) {
|
||||
fetcher->callback(fetcher->data, S_OUT_OF_MEM, NULL);
|
||||
fetcher->callback(fetcher->data, connection_state(S_OUT_OF_MEM), NULL);
|
||||
if (fetcher->ref)
|
||||
*fetcher->ref = NULL;
|
||||
mem_free(fetcher);
|
||||
@ -381,7 +382,7 @@ bittorrent_fetch_callback(struct download *download, void *data)
|
||||
response.source = fragment->data;
|
||||
response.length = fragment->length;
|
||||
|
||||
fetcher->callback(fetcher->data, S_OK, &response);
|
||||
fetcher->callback(fetcher->data, connection_state(S_OK), &response);
|
||||
|
||||
if (fetcher->delete)
|
||||
delete_cache_entry(cached);
|
||||
@ -399,7 +400,7 @@ init_bittorrent_fetch(struct bittorrent_fetcher **fetcher_ref,
|
||||
|
||||
fetcher = mem_calloc(1, sizeof(*fetcher));
|
||||
if (!fetcher) {
|
||||
callback(data, S_OUT_OF_MEM, NULL);
|
||||
callback(data, connection_state(S_OUT_OF_MEM), NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ struct bittorrent_message {
|
||||
LIST_HEAD(struct bittorrent_message);
|
||||
|
||||
struct uri *uri;
|
||||
enum connection_state state;
|
||||
struct connection_state state;
|
||||
unsigned char string[1];
|
||||
};
|
||||
|
||||
@ -411,7 +411,7 @@ del_bittorrent_peer_request(struct bittorrent_peer_status *status,
|
||||
/* URI fetching: */
|
||||
/* ************************************************************************** */
|
||||
|
||||
typedef void (*bittorrent_fetch_callback_T)(void *, enum connection_state,
|
||||
typedef void (*bittorrent_fetch_callback_T)(void *, struct connection_state,
|
||||
struct bittorrent_const_string *);
|
||||
|
||||
struct bittorrent_fetcher *
|
||||
|
@ -305,22 +305,22 @@ init_bittorrent_connection(struct connection *conn)
|
||||
void
|
||||
bittorrent_resume_callback(struct bittorrent_connection *bittorrent)
|
||||
{
|
||||
enum connection_state state;
|
||||
struct connection_state state;
|
||||
|
||||
/* Failing to create the listening socket is fatal. */
|
||||
state = init_bittorrent_listening_socket(bittorrent->conn);
|
||||
if (state != S_OK) {
|
||||
if (!is_in_state(state, S_OK)) {
|
||||
retry_connection(bittorrent->conn, state);
|
||||
return;
|
||||
}
|
||||
|
||||
set_connection_state(bittorrent->conn, S_CONN_TRACKER);
|
||||
set_connection_state(bittorrent->conn, connection_state(S_CONN_TRACKER));
|
||||
send_bittorrent_tracker_request(bittorrent->conn);
|
||||
}
|
||||
|
||||
/* Metainfo file download callback */
|
||||
static void
|
||||
bittorrent_metainfo_callback(void *data, enum connection_state state,
|
||||
bittorrent_metainfo_callback(void *data, struct connection_state state,
|
||||
struct bittorrent_const_string *response)
|
||||
{
|
||||
struct connection *conn = data;
|
||||
@ -328,7 +328,7 @@ bittorrent_metainfo_callback(void *data, enum connection_state state,
|
||||
|
||||
bittorrent->fetch = NULL;
|
||||
|
||||
if (state != S_OK) {
|
||||
if (!is_in_state(state, S_OK)) {
|
||||
abort_connection(conn, state);
|
||||
return;
|
||||
}
|
||||
@ -358,21 +358,22 @@ bittorrent_metainfo_callback(void *data, enum connection_state state,
|
||||
return;
|
||||
|
||||
case BITTORRENT_STATE_CACHE_RESUME:
|
||||
set_connection_state(bittorrent->conn, S_RESUME);
|
||||
set_connection_state(bittorrent->conn,
|
||||
connection_state(S_RESUME));
|
||||
return;
|
||||
|
||||
case BITTORRENT_STATE_OUT_OF_MEM:
|
||||
state = S_OUT_OF_MEM;
|
||||
state = connection_state(S_OUT_OF_MEM);
|
||||
break;
|
||||
|
||||
default:
|
||||
state = S_BITTORRENT_ERROR;
|
||||
state = connection_state(S_BITTORRENT_ERROR);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case BITTORRENT_STATE_OUT_OF_MEM:
|
||||
state = S_OUT_OF_MEM;
|
||||
state = connection_state(S_OUT_OF_MEM);
|
||||
break;
|
||||
|
||||
case BITTORRENT_STATE_ERROR:
|
||||
@ -382,7 +383,7 @@ bittorrent_metainfo_callback(void *data, enum connection_state state,
|
||||
* looking at the protocol header, however, direct usage of the
|
||||
* internal bittorrent: is at your own risk ... at least for
|
||||
* now. --jonas */
|
||||
state = S_BITTORRENT_METAINFO;
|
||||
state = connection_state(S_BITTORRENT_METAINFO);
|
||||
}
|
||||
|
||||
abort_connection(conn, state);
|
||||
@ -397,7 +398,7 @@ bittorrent_protocol_handler(struct connection *conn)
|
||||
|
||||
bittorrent = init_bittorrent_connection(conn);
|
||||
if (!bittorrent) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -405,11 +406,11 @@ bittorrent_protocol_handler(struct connection *conn)
|
||||
uri = get_uri(conn->uri->data, 0);
|
||||
|
||||
if (!uri) {
|
||||
abort_connection(conn, S_BITTORRENT_BAD_URL);
|
||||
abort_connection(conn, connection_state(S_BITTORRENT_BAD_URL));
|
||||
return;
|
||||
}
|
||||
|
||||
set_connection_state(conn, S_CONN);
|
||||
set_connection_state(conn, connection_state(S_CONN));
|
||||
set_connection_timeout(conn);
|
||||
conn->from = 0;
|
||||
|
||||
|
@ -531,7 +531,7 @@ draw_bittorrent_piece_progress(struct download *download, struct terminal *term,
|
||||
}
|
||||
}
|
||||
|
||||
if (download->state == S_RESUME) {
|
||||
if (is_in_state(download->state, S_RESUME)) {
|
||||
static unsigned char s[] = "????"; /* Reduce or enlarge at will. */
|
||||
unsigned int slen = 0;
|
||||
int max = int_min(sizeof(s), width) - 1;
|
||||
@ -587,9 +587,10 @@ bittorrent_message_dialog(struct session *ses, void *data)
|
||||
add_to_string(&string, ":\n\n");
|
||||
}
|
||||
|
||||
if (message->state != S_OK) {
|
||||
if (!is_in_state(message->state, S_OK)) {
|
||||
add_format_to_string(&string, "%s: %s",
|
||||
get_state_message(S_BITTORRENT_TRACKER, ses->tab->term),
|
||||
get_state_message(connection_state(S_BITTORRENT_TRACKER),
|
||||
ses->tab->term),
|
||||
get_state_message(message->state, ses->tab->term));
|
||||
} else {
|
||||
add_to_string(&string, message->string);
|
||||
@ -686,7 +687,7 @@ tp_show_header(struct dialog_data *dlg_data, struct widget_data *widget_data)
|
||||
|
||||
/* Build a dialog querying the user on how to handle a .torrent file. */
|
||||
static void
|
||||
bittorrent_query_callback(void *data, enum connection_state state,
|
||||
bittorrent_query_callback(void *data, struct connection_state state,
|
||||
struct bittorrent_const_string *response)
|
||||
{
|
||||
/* [gettext_accelerator_context(.bittorrent_query_callback)] */
|
||||
@ -705,7 +706,7 @@ bittorrent_query_callback(void *data, enum connection_state state,
|
||||
struct string msg;
|
||||
int files;
|
||||
|
||||
if (state != S_OK)
|
||||
if (!is_in_state(state, S_OK))
|
||||
return;
|
||||
|
||||
/* This should never happen, since setup_download_handler() should make
|
||||
@ -739,7 +740,8 @@ bittorrent_query_callback(void *data, enum connection_state state,
|
||||
done_string(&filename);
|
||||
|
||||
if (parse_bittorrent_metafile(&meta, response) != BITTORRENT_STATE_OK) {
|
||||
print_error_dialog(type_query->ses, S_BITTORRENT_METAINFO,
|
||||
print_error_dialog(type_query->ses,
|
||||
connection_state(S_BITTORRENT_METAINFO),
|
||||
type_query->uri, PRI_CANCEL);
|
||||
tp_cancel(type_query);
|
||||
done_string(&msg);
|
||||
|
@ -67,7 +67,7 @@ find_bittorrent_connection(bittorrent_id_T info_hash)
|
||||
|
||||
static void
|
||||
check_bittorrent_peer_blacklisting(struct bittorrent_peer_connection *peer,
|
||||
enum connection_state state)
|
||||
struct connection_state state)
|
||||
{
|
||||
enum bittorrent_blacklist_flags flags = BITTORRENT_BLACKLIST_NONE;
|
||||
|
||||
@ -75,21 +75,25 @@ check_bittorrent_peer_blacklisting(struct bittorrent_peer_connection *peer,
|
||||
|| !get_opt_bool("protocol.http.bugs.allow_blacklist", NULL))
|
||||
return;
|
||||
|
||||
switch (state) {
|
||||
case -ECONNREFUSED:
|
||||
case -ENETUNREACH:
|
||||
flags |= BITTORRENT_BLACKLIST_PEER_POOL;
|
||||
break;
|
||||
|
||||
case S_CANT_WRITE:
|
||||
case S_CANT_READ:
|
||||
if (!peer->local.handshake
|
||||
|| !peer->remote.handshake)
|
||||
if (is_system_error(state)) {
|
||||
switch (state.syserr) {
|
||||
case ECONNREFUSED:
|
||||
case ENETUNREACH:
|
||||
flags |= BITTORRENT_BLACKLIST_PEER_POOL;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (state.basic) {
|
||||
case S_CANT_WRITE:
|
||||
case S_CANT_READ:
|
||||
if (!peer->local.handshake
|
||||
|| !peer->remote.handshake)
|
||||
flags |= BITTORRENT_BLACKLIST_PEER_POOL;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags != BITTORRENT_BLACKLIST_NONE) {
|
||||
@ -137,30 +141,30 @@ set_bittorrent_peer_connection_timeout(struct bittorrent_peer_connection *peer)
|
||||
* S_DMS (while looking up the host) then moves to S_CONN (while connecting),
|
||||
* and should hopefully become S_TRANS (while transfering). Note, state can hold
|
||||
* both internally defined connection states as described above and errno
|
||||
* values, such as ECONNREFUSED. The errno values are passed negative so in the
|
||||
* previous example the errno would be passed as -ECONNREFUSED. */
|
||||
* values, such as ECONNREFUSED. */
|
||||
static void
|
||||
set_bittorrent_socket_state(struct socket *socket, enum connection_state state)
|
||||
set_bittorrent_socket_state(struct socket *socket, struct connection_state state)
|
||||
{
|
||||
struct bittorrent_peer_connection *peer = socket->conn;
|
||||
|
||||
if (state == S_TRANS && peer->bittorrent)
|
||||
set_connection_state(peer->bittorrent->conn, S_TRANS);
|
||||
if (is_in_state(state, S_TRANS) && peer->bittorrent)
|
||||
set_connection_state(peer->bittorrent->conn,
|
||||
connection_state(S_TRANS));
|
||||
}
|
||||
|
||||
/* Called when progress is made such as when the select() loop detects and
|
||||
* schedules reads and writes. The state variable must be ignored. */
|
||||
static void
|
||||
set_bittorrent_socket_timeout(struct socket *socket, enum connection_state state)
|
||||
set_bittorrent_socket_timeout(struct socket *socket, struct connection_state state)
|
||||
{
|
||||
assert(state == 0);
|
||||
assert(is_in_state(state, 0));
|
||||
set_bittorrent_peer_connection_timeout(socket->conn);
|
||||
}
|
||||
|
||||
/* Called when a non-fatal error condition has appeared, i.e. the condition is
|
||||
* caused by some internal or local system error or simply a timeout. */
|
||||
static void
|
||||
retry_bittorrent_socket(struct socket *socket, enum connection_state state)
|
||||
retry_bittorrent_socket(struct socket *socket, struct connection_state state)
|
||||
{
|
||||
struct bittorrent_peer_connection *peer = socket->conn;
|
||||
|
||||
@ -177,7 +181,7 @@ retry_bittorrent_socket(struct socket *socket, enum connection_state state)
|
||||
/* Called when a fatal and unrecoverable error condition has appeared, such as a
|
||||
* DNS query failed. */
|
||||
static void
|
||||
done_bittorrent_socket(struct socket *socket, enum connection_state state)
|
||||
done_bittorrent_socket(struct socket *socket, struct connection_state state)
|
||||
{
|
||||
struct bittorrent_peer_connection *peer = socket->conn;
|
||||
|
||||
@ -344,7 +348,7 @@ accept_bittorrent_peer_connection(void *____)
|
||||
buffer = alloc_read_buffer(peer->socket);
|
||||
if (!buffer) return;
|
||||
|
||||
read_from_socket(peer->socket, buffer, S_TRANS,
|
||||
read_from_socket(peer->socket, buffer, connection_state(S_TRANS),
|
||||
read_bittorrent_peer_handshake);
|
||||
|
||||
add_to_list(bittorrent_peer_connections, peer);
|
||||
@ -352,7 +356,7 @@ accept_bittorrent_peer_connection(void *____)
|
||||
|
||||
/* Based on network/socket.c:get_pasv_socket() but modified to try and bind to a
|
||||
* port range instead of any port. */
|
||||
enum connection_state
|
||||
struct connection_state
|
||||
init_bittorrent_listening_socket(struct connection *conn)
|
||||
{
|
||||
struct bittorrent_connection *bittorrent = conn->info;
|
||||
@ -366,7 +370,7 @@ init_bittorrent_listening_socket(struct connection *conn)
|
||||
|
||||
/* Has the socket already been initialized? */
|
||||
if (!list_is_singleton(bittorrent_connections))
|
||||
return S_OK;
|
||||
return connection_state(S_OK);
|
||||
|
||||
/* We could have bailed out from an earlier attempt. */
|
||||
if (bittorrent_socket != -1)
|
||||
@ -374,12 +378,12 @@ init_bittorrent_listening_socket(struct connection *conn)
|
||||
|
||||
bittorrent_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (bittorrent_socket < 0)
|
||||
return -errno;
|
||||
return connection_state_for_errno(errno);
|
||||
|
||||
/* Set it non-blocking */
|
||||
|
||||
if (set_nonblocking_fd(bittorrent_socket) < 0)
|
||||
return -errno;
|
||||
return connection_state_for_errno(errno);
|
||||
|
||||
/* Bind it to some port */
|
||||
|
||||
@ -392,11 +396,11 @@ init_bittorrent_listening_socket(struct connection *conn)
|
||||
/* Repeatedly try the configured port range. */
|
||||
while (bind(bittorrent_socket, (struct sockaddr *) &addr, sizeof(addr))) {
|
||||
if (errno != EADDRINUSE)
|
||||
return -errno;
|
||||
return connection_state_for_errno(errno);
|
||||
|
||||
/* If all ports was in use fail with EADDRINUSE. */
|
||||
if (++port > max_port)
|
||||
return -errno;
|
||||
return connection_state_for_errno(errno);
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_port = htons(port);
|
||||
@ -407,20 +411,20 @@ init_bittorrent_listening_socket(struct connection *conn)
|
||||
memset(&addr2, 0, sizeof(addr2));
|
||||
len = sizeof(addr2);
|
||||
if (getsockname(bittorrent_socket, (struct sockaddr *) &addr2, &len))
|
||||
return -errno;
|
||||
return connection_state_for_errno(errno);
|
||||
|
||||
bittorrent->port = ntohs(addr2.sin_port);
|
||||
|
||||
/* Go listen */
|
||||
|
||||
if (listen(bittorrent_socket, LISTEN_BACKLOG))
|
||||
return -errno;
|
||||
return connection_state_for_errno(errno);
|
||||
|
||||
set_ip_tos_throughput(bittorrent_socket);
|
||||
set_handlers(bittorrent_socket, accept_bittorrent_peer_connection,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
return S_OK;
|
||||
return connection_state(S_OK);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -8,7 +8,7 @@
|
||||
struct connection;
|
||||
|
||||
/* Sets up and tears down the peer listening socket. */
|
||||
enum connection_state init_bittorrent_listening_socket(struct connection *conn);
|
||||
struct connection_state init_bittorrent_listening_socket(struct connection *conn);
|
||||
void done_bittorrent_listening_socket(struct connection *conn);
|
||||
|
||||
void done_bittorrent_peer_connection(struct bittorrent_peer_connection *peer);
|
||||
|
@ -349,7 +349,8 @@ do_send_bittorrent_peer_message(struct bittorrent_peer_connection *peer,
|
||||
}
|
||||
|
||||
write_to_socket(peer->socket, string.source, string.length,
|
||||
S_TRANS, sent_bittorrent_peer_message);
|
||||
connection_state(S_TRANS),
|
||||
sent_bittorrent_peer_message);
|
||||
|
||||
done_string(&string);
|
||||
|
||||
@ -658,7 +659,8 @@ read_bittorrent_peer_data(struct socket *socket, struct read_buffer *buffer)
|
||||
break;
|
||||
|
||||
case BITTORRENT_STATE_OUT_OF_MEM:
|
||||
abort_connection(peer->bittorrent->conn, S_OUT_OF_MEM);
|
||||
abort_connection(peer->bittorrent->conn,
|
||||
connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
|
||||
case BITTORRENT_STATE_ERROR:
|
||||
@ -669,7 +671,8 @@ read_bittorrent_peer_data(struct socket *socket, struct read_buffer *buffer)
|
||||
}
|
||||
|
||||
/* Shutdown on fatal errors! */
|
||||
abort_connection(peer->bittorrent->conn, -write_errno);
|
||||
abort_connection(peer->bittorrent->conn,
|
||||
connection_state_for_errno(write_errno));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -710,7 +713,7 @@ sent_bittorrent_peer_handshake(struct socket *socket)
|
||||
send_bittorrent_peer_message(peer, BITTORRENT_MESSAGE_BITFIELD);
|
||||
}
|
||||
|
||||
read_from_socket(peer->socket, buffer, S_TRANS,
|
||||
read_from_socket(peer->socket, buffer, connection_state(S_TRANS),
|
||||
read_bittorrent_peer_data);
|
||||
}
|
||||
|
||||
@ -763,7 +766,8 @@ send_bittorrent_peer_handshake(struct socket *socket)
|
||||
* and we might want to hold on to the old buffer if the peer ID of the
|
||||
* handshake was not read. */
|
||||
write_to_socket(peer->socket, handshake, sizeof(handshake),
|
||||
S_TRANS, sent_bittorrent_peer_handshake);
|
||||
connection_state(S_TRANS),
|
||||
sent_bittorrent_peer_handshake);
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -935,7 +939,8 @@ do_read_bittorrent_peer_handshake(struct socket *socket, struct read_buffer *buf
|
||||
break;
|
||||
}
|
||||
|
||||
read_from_socket(peer->socket, buffer, S_TRANS,
|
||||
read_from_socket(peer->socket, buffer,
|
||||
connection_state(S_TRANS),
|
||||
read_bittorrent_peer_handshake);
|
||||
break;
|
||||
|
||||
@ -945,7 +950,8 @@ do_read_bittorrent_peer_handshake(struct socket *socket, struct read_buffer *buf
|
||||
|
||||
case BITTORRENT_PEER_HANDSHAKE_INCOMPLETE:
|
||||
/* The whole handshake was not read so wait for more. */
|
||||
read_from_socket(peer->socket, buffer, S_TRANS,
|
||||
read_from_socket(peer->socket, buffer,
|
||||
connection_state(S_TRANS),
|
||||
read_bittorrent_peer_handshake);
|
||||
break;
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ set_bittorrent_tracker_interval(struct connection *conn)
|
||||
/* XXX: The data pointer may be NULL when doing event=stopped because no
|
||||
* connection is attached anymore. */
|
||||
static void
|
||||
bittorrent_tracker_callback(void *data, enum connection_state state,
|
||||
bittorrent_tracker_callback(void *data, struct connection_state state,
|
||||
struct bittorrent_const_string *response)
|
||||
{
|
||||
struct connection *conn = data;
|
||||
@ -76,12 +76,12 @@ bittorrent_tracker_callback(void *data, enum connection_state state,
|
||||
|
||||
/* FIXME: We treat any error as fatal here, however, it might be better
|
||||
* to relax that and allow a few errors before ending the connection. */
|
||||
if (state != S_OK) {
|
||||
if (state == S_INTERRUPTED)
|
||||
if (!is_in_state(state, S_OK)) {
|
||||
if (is_in_state(state, S_INTERRUPTED))
|
||||
return;
|
||||
bittorrent->tracker.failed = 1;
|
||||
add_bittorrent_message(conn->uri, state, NULL);
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -103,16 +103,17 @@ bittorrent_tracker_callback(void *data, enum connection_state state,
|
||||
return;
|
||||
|
||||
case BITTORRENT_STATE_OUT_OF_MEM:
|
||||
state = S_OUT_OF_MEM;
|
||||
state = connection_state(S_OUT_OF_MEM);
|
||||
break;
|
||||
|
||||
case BITTORRENT_STATE_REQUEST_FAILURE:
|
||||
add_bittorrent_message(conn->uri, S_OK, response);
|
||||
state = S_OK;
|
||||
add_bittorrent_message(conn->uri, connection_state(S_OK),
|
||||
response);
|
||||
state = connection_state(S_OK);
|
||||
break;
|
||||
|
||||
default:
|
||||
state = S_BITTORRENT_TRACKER;
|
||||
state = connection_state(S_BITTORRENT_TRACKER);
|
||||
}
|
||||
|
||||
abort_connection(conn, state);
|
||||
@ -159,7 +160,8 @@ do_send_bittorrent_tracker_request(struct connection *conn)
|
||||
if (!init_string(&request)) {
|
||||
done_string(&request);
|
||||
if (!stopped)
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn,
|
||||
connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -170,7 +172,8 @@ do_send_bittorrent_tracker_request(struct connection *conn)
|
||||
if (!uri) {
|
||||
done_string(&request);
|
||||
if (!stopped)
|
||||
abort_connection(conn, S_BITTORRENT_ERROR);
|
||||
abort_connection(conn,
|
||||
connection_state(S_BITTORRENT_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -249,7 +252,8 @@ do_send_bittorrent_tracker_request(struct connection *conn)
|
||||
done_string(&request);
|
||||
if (!uri) {
|
||||
if (!stopped)
|
||||
abort_connection(conn, S_BITTORRENT_ERROR);
|
||||
abort_connection(conn,
|
||||
connection_state(S_BITTORRENT_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ close_all_non_term_fd(void)
|
||||
close(n);
|
||||
}
|
||||
|
||||
enum connection_state
|
||||
struct connection_state
|
||||
init_directory_listing(struct string *page, struct uri *uri)
|
||||
{
|
||||
struct string dirpath = NULL_STRING;
|
||||
@ -151,5 +151,7 @@ out_of_memory:
|
||||
done_string(&decoded);
|
||||
done_string(&location);
|
||||
|
||||
return page->length > 0 ? S_OK : S_OUT_OF_MEM;
|
||||
return page->length > 0
|
||||
? connection_state(S_OK)
|
||||
: connection_state(S_OUT_OF_MEM);
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ struct uri;
|
||||
/* Close all non-terminal file descriptors. */
|
||||
void close_all_non_term_fd(void);
|
||||
|
||||
enum connection_state
|
||||
struct connection_state
|
||||
init_directory_listing(struct string *page, struct uri *uri);
|
||||
|
||||
#endif
|
||||
|
@ -120,7 +120,7 @@ data_protocol_handler(struct connection *conn)
|
||||
int base64 = 0;
|
||||
|
||||
if (!cached) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -128,7 +128,7 @@ data_protocol_handler(struct connection *conn)
|
||||
|
||||
data_start = parse_data_protocol_header(conn, &base64);
|
||||
if (!data_start) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -136,7 +136,7 @@ data_protocol_handler(struct connection *conn)
|
||||
* it. */
|
||||
data = memacpy(data_start, uri->datalen - (data_start - uri->data));
|
||||
if (!data) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -144,7 +144,7 @@ data_protocol_handler(struct connection *conn)
|
||||
unsigned char *decoded = base64_encode(data);
|
||||
|
||||
if (!decoded) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -163,5 +163,5 @@ data_protocol_handler(struct connection *conn)
|
||||
|
||||
mem_free(data);
|
||||
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
}
|
||||
|
@ -78,7 +78,8 @@ close_pipe_and_read(struct socket *data_socket)
|
||||
data_socket->fd = -1;
|
||||
|
||||
conn->socket->state = SOCKET_END_ONCLOSE;
|
||||
read_from_socket(conn->socket, rb, S_SENT, http_got_header);
|
||||
read_from_socket(conn->socket, rb, connection_state(S_SENT),
|
||||
http_got_header);
|
||||
}
|
||||
|
||||
|
||||
@ -91,13 +92,13 @@ send_more_post_data(struct socket *socket)
|
||||
struct http_connection_info *http = conn->info;
|
||||
unsigned char buffer[POST_BUFFER_SIZE];
|
||||
int got;
|
||||
enum connection_state error;
|
||||
struct connection_state error;
|
||||
|
||||
got = read_http_post(&http->post, buffer, POST_BUFFER_SIZE, &error);
|
||||
if (got < 0) {
|
||||
abort_connection(conn, error);
|
||||
} else if (got > 0) {
|
||||
write_to_socket(socket, buffer, got, S_TRANS,
|
||||
write_to_socket(socket, buffer, got, connection_state(S_TRANS),
|
||||
send_more_post_data);
|
||||
} else { /* got == 0, meaning end of data */
|
||||
close_pipe_and_read(socket);
|
||||
@ -112,7 +113,7 @@ send_post_data(struct connection *conn)
|
||||
struct http_connection_info *http = conn->info;
|
||||
unsigned char *post = conn->uri->post;
|
||||
unsigned char *postend;
|
||||
enum connection_state error;
|
||||
struct connection_state error;
|
||||
|
||||
postend = strchr(post, '\n');
|
||||
if (postend) post = postend + 1;
|
||||
@ -301,7 +302,7 @@ execute_cgi(struct connection *conn)
|
||||
unsigned char *script;
|
||||
struct stat buf;
|
||||
pid_t pid;
|
||||
enum connection_state state = S_OK;
|
||||
struct connection_state state = connection_state(S_OK);
|
||||
int pipe_read[2], pipe_write[2];
|
||||
|
||||
if (!get_opt_bool("protocol.file.cgi.policy", NULL)) return 1;
|
||||
@ -313,7 +314,7 @@ execute_cgi(struct connection *conn)
|
||||
|
||||
script = get_uri_string(conn->uri, URI_PATH);
|
||||
if (!script) {
|
||||
state = S_OUT_OF_MEM;
|
||||
state = connection_state(S_OUT_OF_MEM);
|
||||
goto end2;
|
||||
}
|
||||
decode_uri(script);
|
||||
@ -344,13 +345,13 @@ execute_cgi(struct connection *conn)
|
||||
}
|
||||
|
||||
if (c_pipe(pipe_read) || c_pipe(pipe_write)) {
|
||||
state = -errno;
|
||||
state = connection_state_for_errno(errno);
|
||||
goto end1;
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
state = -errno;
|
||||
state = connection_state_for_errno(errno);
|
||||
goto end0;
|
||||
}
|
||||
if (!pid) { /* CGI script */
|
||||
|
@ -174,34 +174,34 @@ add_dir_entries(struct directory_entry *entries, unsigned char *dirpath,
|
||||
/* Generates an HTML page listing the content of @directory with the path
|
||||
* @dirpath. */
|
||||
/* Returns a connection state. S_OK if all is well. */
|
||||
static inline enum connection_state
|
||||
static inline struct connection_state
|
||||
list_directory(struct connection *conn, unsigned char *dirpath,
|
||||
struct string *page)
|
||||
{
|
||||
int show_hidden_files = get_opt_bool("protocol.file.show_hidden_files",
|
||||
NULL);
|
||||
struct directory_entry *entries;
|
||||
enum connection_state state;
|
||||
struct connection_state state;
|
||||
|
||||
errno = 0;
|
||||
entries = get_directory_entries(dirpath, show_hidden_files);
|
||||
if (!entries) {
|
||||
if (errno) return -errno;
|
||||
return S_OUT_OF_MEM;
|
||||
if (errno) return connection_state_for_errno(errno);
|
||||
return connection_state(S_OUT_OF_MEM);
|
||||
}
|
||||
|
||||
state = init_directory_listing(page, conn->uri);
|
||||
if (state != S_OK)
|
||||
return S_OUT_OF_MEM;
|
||||
if (!is_in_state(state, S_OK))
|
||||
return connection_state(S_OUT_OF_MEM);
|
||||
|
||||
add_dir_entries(entries, dirpath, page);
|
||||
|
||||
if (!add_to_string(page, "</pre>\n<hr/>\n</body>\n</html>\n")) {
|
||||
done_string(page);
|
||||
return S_OUT_OF_MEM;
|
||||
return connection_state(S_OUT_OF_MEM);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
return connection_state(S_OK);
|
||||
}
|
||||
|
||||
|
||||
@ -216,13 +216,14 @@ file_protocol_handler(struct connection *connection)
|
||||
{
|
||||
unsigned char *redirect_location = NULL;
|
||||
struct string page, name;
|
||||
enum connection_state state;
|
||||
struct connection_state state;
|
||||
int set_dir_content_type = 0;
|
||||
|
||||
if (get_cmd_opt_bool("anonymous")) {
|
||||
if (strcmp(connection->uri->string, "file:///dev/stdin")
|
||||
|| isatty(STDIN_FILENO)) {
|
||||
abort_connection(connection, S_FILE_ANONYMOUS);
|
||||
abort_connection(connection,
|
||||
connection_state(S_FILE_ANONYMOUS));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -240,7 +241,7 @@ file_protocol_handler(struct connection *connection)
|
||||
if (!init_string(&name)
|
||||
|| !add_uri_to_string(&name, connection->uri, URI_PATH)) {
|
||||
done_string(&name);
|
||||
abort_connection(connection, S_OUT_OF_MEM);
|
||||
abort_connection(connection, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -255,7 +256,7 @@ file_protocol_handler(struct connection *connection)
|
||||
* directory separator. */
|
||||
if (name.source[0] && !dir_sep(name.source[name.length - 1])) {
|
||||
redirect_location = STRING_DIR_SEP;
|
||||
state = S_OK;
|
||||
state = connection_state(S_OK);
|
||||
} else {
|
||||
state = list_directory(connection, name.source, &page);
|
||||
set_dir_content_type = 1;
|
||||
@ -269,7 +270,7 @@ file_protocol_handler(struct connection *connection)
|
||||
|
||||
done_string(&name);
|
||||
|
||||
if (state == S_OK) {
|
||||
if (is_in_state(state, S_OK)) {
|
||||
struct cache_entry *cached;
|
||||
|
||||
/* Try to add fragment data to the connection cache if either
|
||||
@ -277,11 +278,11 @@ file_protocol_handler(struct connection *connection)
|
||||
cached = connection->cached = get_cache_entry(connection->uri);
|
||||
if (!connection->cached) {
|
||||
if (!redirect_location) done_string(&page);
|
||||
state = S_OUT_OF_MEM;
|
||||
state = connection_state(S_OUT_OF_MEM);
|
||||
|
||||
} else if (redirect_location) {
|
||||
if (!redirect_cache(cached, redirect_location, 1, 0))
|
||||
state = S_OUT_OF_MEM;
|
||||
state = connection_state(S_OUT_OF_MEM);
|
||||
|
||||
} else {
|
||||
add_fragment(cached, 0, page.source, page.length);
|
||||
@ -301,7 +302,7 @@ file_protocol_handler(struct connection *connection)
|
||||
/* Not so gracefully handle failed memory
|
||||
* allocation. */
|
||||
if (!head)
|
||||
state = S_OUT_OF_MEM;
|
||||
state = connection_state(S_OUT_OF_MEM);
|
||||
|
||||
/* Setup directory listing for viewing. */
|
||||
mem_free_set(&cached->head, head);
|
||||
|
@ -35,13 +35,13 @@ finger_get_response(struct socket *socket, struct read_buffer *rb)
|
||||
int l;
|
||||
|
||||
if (!cached) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
conn->cached = cached;
|
||||
|
||||
if (socket->state == SOCKET_CLOSED) {
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -53,7 +53,8 @@ finger_get_response(struct socket *socket, struct read_buffer *rb)
|
||||
|
||||
conn->from += l;
|
||||
kill_buffer_data(rb, l);
|
||||
read_from_socket(conn->socket, rb, S_TRANS, finger_get_response);
|
||||
read_from_socket(conn->socket, rb, connection_state(S_TRANS),
|
||||
finger_get_response);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -70,7 +71,8 @@ finger_send_request(struct socket *socket)
|
||||
add_bytes_to_string(&req, conn->uri->user, conn->uri->userlen);
|
||||
}
|
||||
add_crlf_to_string(&req);
|
||||
request_from_socket(socket, req.source, req.length, S_SENT,
|
||||
request_from_socket(socket, req.source, req.length,
|
||||
connection_state(S_SENT),
|
||||
SOCKET_END_ONCLOSE, finger_get_response);
|
||||
done_string(&req);
|
||||
}
|
||||
|
@ -61,11 +61,11 @@ struct module fsp_protocol_module = struct_module(
|
||||
*
|
||||
* - If an error occurs, the child process writes "text/x-error"
|
||||
* without newline to stderr, and an error code and a newline to
|
||||
* stdout. The error code is either from errno or a negated value
|
||||
* from enum connection_state, e.g. -S_OUT_OF_MEM. In particular,
|
||||
* EPERM causes the parent process to prompt for username and
|
||||
* password. (In this, fsplib differs from libsmbclient, which uses
|
||||
* EACCES if authentication fails.)
|
||||
* stdout. The error code is either "S" followed by errno or "I"
|
||||
* followed by enum connection_basic_state. In particular, EPERM
|
||||
* causes the parent process to prompt for username and password.
|
||||
* (In this, fsplib differs from libsmbclient, which uses EACCES if
|
||||
* authentication fails.)
|
||||
*
|
||||
* - If the resource is a regular file, the child process writes the
|
||||
* estimated length of the file (in bytes) and a newline to stderr,
|
||||
@ -90,9 +90,12 @@ struct module fsp_protocol_module = struct_module(
|
||||
* stdout fails for directory listing like we do for file fetching. */
|
||||
|
||||
static void
|
||||
fsp_error(int error)
|
||||
fsp_error(struct connection_state error)
|
||||
{
|
||||
printf("%d\n", error);
|
||||
if (is_system_error(error))
|
||||
printf("S%d\n", (int) error.syserr);
|
||||
else
|
||||
printf("I%d\n", (int) error.basic);
|
||||
fprintf(stderr, "text/x-error");
|
||||
/* In principle, this should perhaps call fsp_close_session to
|
||||
* make the server accept any key from the next client process
|
||||
@ -202,13 +205,13 @@ fsp_directory(FSP_SESSION *ses, struct uri *uri)
|
||||
unsigned char dircolor[8] = "";
|
||||
|
||||
if (!data)
|
||||
fsp_error(-S_OUT_OF_MEM);
|
||||
fsp_error(connection_state(S_OUT_OF_MEM));
|
||||
decode_uri(data);
|
||||
if (init_directory_listing(&buf, uri) != S_OK)
|
||||
fsp_error(-S_OUT_OF_MEM);
|
||||
if (!is_in_state(init_directory_listing(&buf, uri), S_OK))
|
||||
fsp_error(connection_state(S_OUT_OF_MEM));
|
||||
|
||||
dir = fsp_opendir(ses, data);
|
||||
if (!dir) fsp_error(errno);
|
||||
if (!dir) fsp_error(connection_state_for_errno(errno));
|
||||
|
||||
fprintf(stderr, "text/html");
|
||||
fclose(stderr);
|
||||
@ -249,8 +252,18 @@ do_fsp(struct connection *conn)
|
||||
if (auth) password = auth->password;
|
||||
}
|
||||
|
||||
/* fsp_open_session may not set errno if getaddrinfo fails
|
||||
* https://sourceforge.net/tracker/index.php?func=detail&aid=2036798&group_id=93841&atid=605738
|
||||
* Try to detect this bug and use an ELinks-specific error
|
||||
* code instead, so that we can display a message anyway. */
|
||||
errno = 0;
|
||||
ses = fsp_open_session(host, port, password);
|
||||
if (!ses) fsp_error(errno);
|
||||
if (!ses) {
|
||||
if (errno)
|
||||
fsp_error(connection_state_for_errno(errno));
|
||||
else
|
||||
fsp_error(connection_state(S_FSP_OPEN_SESSION_UNKN));
|
||||
}
|
||||
|
||||
/* fsplib 0.8 ABI depends on _FILE_OFFSET_BITS
|
||||
* https://sourceforge.net/tracker/index.php?func=detail&aid=1674729&group_id=93841&atid=605738
|
||||
@ -270,7 +283,7 @@ do_fsp(struct connection *conn)
|
||||
* sb.st_size really needs to be filled, but filling the rest
|
||||
* too helps viewing the data with a debugger.) */
|
||||
memset(&sb, 0xAA, sizeof(sb));
|
||||
if (fsp_stat(ses, data, &sb)) fsp_error(errno);
|
||||
if (fsp_stat(ses, data, &sb)) fsp_error(connection_state_for_errno(errno));
|
||||
|
||||
if (S_ISDIR(sb.st_mode)) {
|
||||
fsp_directory(ses, uri);
|
||||
@ -280,7 +293,7 @@ do_fsp(struct connection *conn)
|
||||
int r;
|
||||
|
||||
if (!file) {
|
||||
fsp_error(errno);
|
||||
fsp_error(connection_state_for_errno(errno));
|
||||
}
|
||||
|
||||
#if SIZEOF_OFF_T >= 8
|
||||
@ -334,7 +347,7 @@ static void
|
||||
prompt_username_pw(struct connection *conn)
|
||||
{
|
||||
add_auth_entry(conn->uri, "FSP", NULL, NULL, 0);
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -342,10 +355,10 @@ fsp_got_error(struct socket *socket, struct read_buffer *rb)
|
||||
{
|
||||
int len = rb->length;
|
||||
struct connection *conn = socket->conn;
|
||||
int error;
|
||||
struct connection_state error;
|
||||
|
||||
if (len < 0) {
|
||||
abort_connection(conn, -errno);
|
||||
abort_connection(conn, connection_state_for_errno(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -355,20 +368,28 @@ fsp_got_error(struct socket *socket, struct read_buffer *rb)
|
||||
* pipe. */
|
||||
assert(rb->freespace >= 1);
|
||||
if_assert_failed {
|
||||
abort_connection(conn, S_INTERNAL);
|
||||
abort_connection(conn, connection_state(S_INTERNAL));
|
||||
return;
|
||||
}
|
||||
rb->data[len] = '\0';
|
||||
error = atoi(rb->data);
|
||||
kill_buffer_data(rb, len);
|
||||
switch (error) {
|
||||
case EPERM:
|
||||
prompt_username_pw(conn);
|
||||
switch (rb->data[0]) {
|
||||
case 'S':
|
||||
error = connection_state_for_errno(atoi(rb->data + 1));
|
||||
break;
|
||||
case 'I':
|
||||
error = connection_state(atoi(rb->data + 1));
|
||||
break;
|
||||
default:
|
||||
abort_connection(conn, -error);
|
||||
ERROR("malformed error code: %s", rb->data);
|
||||
error = connection_state(S_INTERNAL);
|
||||
break;
|
||||
}
|
||||
kill_buffer_data(rb, len);
|
||||
|
||||
if (is_system_error(error) && error.syserr == EPERM)
|
||||
prompt_username_pw(conn);
|
||||
else
|
||||
abort_connection(conn, error);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -378,12 +399,12 @@ fsp_got_data(struct socket *socket, struct read_buffer *rb)
|
||||
struct connection *conn = socket->conn;
|
||||
|
||||
if (len < 0) {
|
||||
abort_connection(conn, -errno);
|
||||
abort_connection(conn, connection_state_for_errno(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!len) {
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -394,7 +415,7 @@ fsp_got_data(struct socket *socket, struct read_buffer *rb)
|
||||
conn->from += len;
|
||||
kill_buffer_data(rb, len);
|
||||
|
||||
read_from_socket(socket, rb, S_TRANS, fsp_got_data);
|
||||
read_from_socket(socket, rb, connection_state(S_TRANS), fsp_got_data);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -413,7 +434,7 @@ fsp_got_header(struct socket *socket, struct read_buffer *rb)
|
||||
* and assume abort_connection will do them?) */
|
||||
close_socket(socket);
|
||||
close_socket(conn->data_socket);
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
socket->state = SOCKET_END_ONCLOSE;
|
||||
@ -436,7 +457,7 @@ fsp_got_header(struct socket *socket, struct read_buffer *rb)
|
||||
|
||||
/* avoid read from socket error */
|
||||
if (!conn->est_length) {
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -451,15 +472,17 @@ fsp_got_header(struct socket *socket, struct read_buffer *rb)
|
||||
if (!buf) {
|
||||
close_socket(socket);
|
||||
close_socket(conn->data_socket);
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
mem_free_set(&conn->cached->content_type, stracpy("text/html"));
|
||||
read_from_socket(conn->data_socket, buf, S_CONN, fsp_got_error);
|
||||
read_from_socket(conn->data_socket, buf,
|
||||
connection_state(S_CONN), fsp_got_error);
|
||||
} else {
|
||||
read_from_socket(conn->data_socket, buf, S_CONN, fsp_got_data);
|
||||
read_from_socket(conn->data_socket, buf,
|
||||
connection_state(S_CONN), fsp_got_data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -478,7 +501,7 @@ fsp_protocol_handler(struct connection *conn)
|
||||
if (fsp_pipe[1] >= 0) close(fsp_pipe[1]);
|
||||
if (header_pipe[0] >= 0) close(header_pipe[0]);
|
||||
if (header_pipe[1] >= 0) close(header_pipe[1]);
|
||||
abort_connection(conn, -s_errno);
|
||||
abort_connection(conn, connection_state_for_errno(s_errno));
|
||||
return;
|
||||
}
|
||||
conn->from = 0;
|
||||
@ -493,7 +516,7 @@ fsp_protocol_handler(struct connection *conn)
|
||||
close(fsp_pipe[1]);
|
||||
close(header_pipe[0]);
|
||||
close(header_pipe[1]);
|
||||
retry_connection(conn, -s_errno);
|
||||
retry_connection(conn, connection_state_for_errno(s_errno));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -531,9 +554,10 @@ fsp_protocol_handler(struct connection *conn)
|
||||
if (!buf2) {
|
||||
close_socket(conn->data_socket);
|
||||
close_socket(conn->socket);
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
read_from_socket(conn->socket, buf2, S_CONN, fsp_got_header);
|
||||
read_from_socket(conn->socket, buf2,
|
||||
connection_state(S_CONN), fsp_got_header);
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ struct ftp_connection_info {
|
||||
|
||||
/* Prototypes */
|
||||
static void ftp_login(struct socket *);
|
||||
static void ftp_send_retr_req(struct connection *, int);
|
||||
static void ftp_send_retr_req(struct connection *, struct connection_state);
|
||||
static void ftp_got_info(struct socket *, struct read_buffer *);
|
||||
static void ftp_got_user_info(struct socket *, struct read_buffer *);
|
||||
static void ftp_pass(struct connection *);
|
||||
@ -127,7 +127,7 @@ static void ftp_pass_info(struct socket *, struct read_buffer *);
|
||||
static void ftp_retr_file(struct socket *, struct read_buffer *);
|
||||
static void ftp_got_final_response(struct socket *, struct read_buffer *);
|
||||
static void got_something_from_data_connection(struct connection *);
|
||||
static void ftp_end_request(struct connection *, enum connection_state);
|
||||
static void ftp_end_request(struct connection *, struct connection_state);
|
||||
static struct ftp_connection_info *add_file_cmd_to_str(struct connection *);
|
||||
static void ftp_data_accept(struct connection *conn);
|
||||
|
||||
@ -276,13 +276,14 @@ ftp_protocol_handler(struct connection *conn)
|
||||
conn->cache_mode >= CACHE_MODE_FORCE_RELOAD);
|
||||
|
||||
} else {
|
||||
ftp_send_retr_req(conn, S_SENT);
|
||||
ftp_send_retr_req(conn, connection_state(S_SENT));
|
||||
}
|
||||
}
|
||||
|
||||
/* Send command, set connection state and free cmd string. */
|
||||
static void
|
||||
send_cmd(struct connection *conn, struct string *cmd, void *callback, int state)
|
||||
send_cmd(struct connection *conn, struct string *cmd, void *callback,
|
||||
struct connection_state state)
|
||||
{
|
||||
request_from_socket(conn->socket, cmd->source, cmd->length, state,
|
||||
SOCKET_RETRY_ONCLOSE, callback);
|
||||
@ -308,20 +309,20 @@ prompt_username_pw(struct connection *conn)
|
||||
if (!conn->cached) {
|
||||
conn->cached = get_cache_entry(conn->uri);
|
||||
if (!conn->cached) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mem_free_set(&conn->cached->content_type, stracpy("text/html"));
|
||||
if (!conn->cached->content_type) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
add_auth_entry(conn->uri, "FTP Login", NULL, NULL, 0);
|
||||
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
}
|
||||
|
||||
/* Send USER command. */
|
||||
@ -335,7 +336,7 @@ ftp_login(struct socket *socket)
|
||||
auth = find_auth(conn->uri);
|
||||
|
||||
if (!init_string(&cmd)) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -353,7 +354,7 @@ ftp_login(struct socket *socket)
|
||||
}
|
||||
add_crlf_to_string(&cmd);
|
||||
|
||||
send_cmd(conn, &cmd, (void *) ftp_got_info, S_SENT);
|
||||
send_cmd(conn, &cmd, (void *) ftp_got_info, connection_state(S_SENT));
|
||||
}
|
||||
|
||||
/* Parse connection response. */
|
||||
@ -364,7 +365,7 @@ ftp_got_info(struct socket *socket, struct read_buffer *rb)
|
||||
int response = get_ftp_response(conn, rb, 0, NULL);
|
||||
|
||||
if (response == -1) {
|
||||
abort_connection(conn, S_FTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_FTP_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -380,7 +381,7 @@ ftp_got_info(struct socket *socket, struct read_buffer *rb)
|
||||
|
||||
if (response != 220) {
|
||||
/* TODO? Retry in case of ... ?? */
|
||||
retry_connection(conn, S_FTP_UNAVAIL);
|
||||
retry_connection(conn, connection_state(S_FTP_UNAVAIL));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -396,7 +397,7 @@ ftp_got_user_info(struct socket *socket, struct read_buffer *rb)
|
||||
int response = get_ftp_response(conn, rb, 0, NULL);
|
||||
|
||||
if (response == -1) {
|
||||
abort_connection(conn, S_FTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_FTP_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -426,12 +427,12 @@ ftp_got_user_info(struct socket *socket, struct read_buffer *rb)
|
||||
* non-RFC compliant servers may return even something other than 421.
|
||||
* --Zas */
|
||||
if (response >= 400) {
|
||||
abort_connection(conn, S_FTP_UNAVAIL);
|
||||
abort_connection(conn, connection_state(S_FTP_UNAVAIL));
|
||||
return;
|
||||
}
|
||||
|
||||
if (response == 230) {
|
||||
ftp_send_retr_req(conn, S_GETH);
|
||||
ftp_send_retr_req(conn, connection_state(S_GETH));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -448,7 +449,7 @@ ftp_pass(struct connection *conn)
|
||||
auth = find_auth(conn->uri);
|
||||
|
||||
if (!init_string(&cmd)) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -471,7 +472,7 @@ ftp_pass(struct connection *conn)
|
||||
}
|
||||
add_crlf_to_string(&cmd);
|
||||
|
||||
send_cmd(conn, &cmd, (void *) ftp_pass_info, S_LOGIN);
|
||||
send_cmd(conn, &cmd, (void *) ftp_pass_info, connection_state(S_LOGIN));
|
||||
}
|
||||
|
||||
/* Parse PASS command response. */
|
||||
@ -482,12 +483,13 @@ ftp_pass_info(struct socket *socket, struct read_buffer *rb)
|
||||
int response = get_ftp_response(conn, rb, 0, NULL);
|
||||
|
||||
if (response == -1) {
|
||||
abort_connection(conn, S_FTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_FTP_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!response) {
|
||||
read_from_socket(conn->socket, rb, S_LOGIN, ftp_pass_info);
|
||||
read_from_socket(conn->socket, rb, connection_state(S_LOGIN),
|
||||
ftp_pass_info);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -509,11 +511,11 @@ ftp_pass_info(struct socket *socket, struct read_buffer *rb)
|
||||
}
|
||||
|
||||
if (response >= 400) {
|
||||
abort_connection(conn, S_FTP_UNAVAIL);
|
||||
abort_connection(conn, connection_state(S_FTP_UNAVAIL));
|
||||
return;
|
||||
}
|
||||
|
||||
ftp_send_retr_req(conn, S_GETH);
|
||||
ftp_send_retr_req(conn, connection_state(S_GETH));
|
||||
}
|
||||
|
||||
/* Construct PORT command. */
|
||||
@ -674,14 +676,14 @@ add_file_cmd_to_str(struct connection *conn)
|
||||
|
||||
if (!conn->uri->data) {
|
||||
INTERNAL("conn->uri->data empty");
|
||||
abort_connection(conn, S_INTERNAL);
|
||||
abort_connection(conn, connection_state(S_INTERNAL));
|
||||
goto ret;
|
||||
}
|
||||
|
||||
assert(conn->info == NULL);
|
||||
assert(conn->done == NULL);
|
||||
if_assert_failed {
|
||||
abort_connection(conn, S_INTERNAL);
|
||||
abort_connection(conn, connection_state(S_INTERNAL));
|
||||
goto ret;
|
||||
}
|
||||
|
||||
@ -692,7 +694,7 @@ add_file_cmd_to_str(struct connection *conn)
|
||||
* risky. */
|
||||
ftp = mem_calloc(1, sizeof(*ftp));
|
||||
if (!ftp) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
goto ret;
|
||||
}
|
||||
|
||||
@ -702,24 +704,24 @@ add_file_cmd_to_str(struct connection *conn)
|
||||
if (!init_string(&command)
|
||||
|| !init_string(&ftp_data_command)
|
||||
|| !init_string(&pathname)) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
goto ret;
|
||||
}
|
||||
|
||||
if (!get_ftp_data_socket(conn, &ftp_data_command)) {
|
||||
INTERNAL("Ftp data socket failure");
|
||||
abort_connection(conn, S_INTERNAL);
|
||||
abort_connection(conn, connection_state(S_INTERNAL));
|
||||
goto ret;
|
||||
}
|
||||
|
||||
if (!add_uri_to_string(&pathname, conn->uri, URI_PATH)) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
goto ret;
|
||||
}
|
||||
|
||||
decode_uri_string(&pathname);
|
||||
if (!is_ftp_pathname_safe(&pathname)) {
|
||||
abort_connection(conn, S_BAD_URL);
|
||||
abort_connection(conn, connection_state(S_BAD_URL));
|
||||
goto ret;
|
||||
}
|
||||
|
||||
@ -741,7 +743,7 @@ add_file_cmd_to_str(struct connection *conn)
|
||||
|
||||
|| !add_to_string(&command, "LIST")
|
||||
|| !add_crlf_to_string(&command)) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
goto ret;
|
||||
}
|
||||
|
||||
@ -757,7 +759,7 @@ add_file_cmd_to_str(struct connection *conn)
|
||||
|| !add_crlf_to_string(&command)
|
||||
|
||||
|| !add_string_to_string(&command, &ftp_data_command)) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
goto ret;
|
||||
}
|
||||
|
||||
@ -769,7 +771,7 @@ add_file_cmd_to_str(struct connection *conn)
|
||||
if (!add_to_string(&command, "REST ")
|
||||
|| !add_long_to_string(&command, offset)
|
||||
|| !add_crlf_to_string(&command)) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
goto ret;
|
||||
}
|
||||
|
||||
@ -780,7 +782,7 @@ add_file_cmd_to_str(struct connection *conn)
|
||||
if (!add_to_string(&command, "RETR ")
|
||||
|| !add_string_to_string(&command, &pathname)
|
||||
|| !add_crlf_to_string(&command)) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
goto ret;
|
||||
}
|
||||
}
|
||||
@ -790,7 +792,7 @@ add_file_cmd_to_str(struct connection *conn)
|
||||
/* 1 byte is already reserved for cmd_buffer in struct ftp_connection_info. */
|
||||
ftp = mem_realloc(ftp, sizeof(*ftp) + command.length);
|
||||
if (!ftp) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
goto ret;
|
||||
}
|
||||
conn->info = ftp; /* in case mem_realloc moved the buffer */
|
||||
@ -825,12 +827,12 @@ send_it_line_by_line(struct connection *conn, struct string *cmd)
|
||||
|
||||
/* Send commands to retrieve file or directory. */
|
||||
static void
|
||||
ftp_send_retr_req(struct connection *conn, int state)
|
||||
ftp_send_retr_req(struct connection *conn, struct connection_state state)
|
||||
{
|
||||
struct string cmd;
|
||||
|
||||
if (!init_string(&cmd)) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -925,13 +927,13 @@ ftp_data_connect(struct connection *conn, int pf, struct sockaddr_storage *sa,
|
||||
if (conn->data_socket->fd != -1) {
|
||||
/* The server maliciously sent multiple 227 or 229
|
||||
* responses. Do not leak the previous data_socket. */
|
||||
abort_connection(conn, S_FTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_FTP_ERROR));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = socket(pf, SOCK_STREAM, 0);
|
||||
if (fd < 0 || set_nonblocking_fd(fd) < 0) {
|
||||
abort_connection(conn, S_FTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_FTP_ERROR));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -956,12 +958,14 @@ ftp_retr_file(struct socket *socket, struct read_buffer *rb)
|
||||
response = get_ftp_response(conn, rb, 0, &sa);
|
||||
|
||||
if (response == -1) {
|
||||
abort_connection(conn, S_FTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_FTP_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!response) {
|
||||
read_from_socket(conn->socket, rb, S_GETH, ftp_retr_file);
|
||||
read_from_socket(conn->socket, rb,
|
||||
connection_state(S_GETH),
|
||||
ftp_retr_file);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -986,7 +990,8 @@ ftp_retr_file(struct socket *socket, struct read_buffer *rb)
|
||||
|
||||
case 2: /* PORT */
|
||||
if (response >= 400) {
|
||||
abort_connection(conn, S_FTP_PORT);
|
||||
abort_connection(conn,
|
||||
connection_state(S_FTP_PORT));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@ -995,7 +1000,7 @@ ftp_retr_file(struct socket *socket, struct read_buffer *rb)
|
||||
if (response >= 400) {
|
||||
if (ftp->dir) {
|
||||
abort_connection(conn,
|
||||
S_FTP_NO_FILE);
|
||||
connection_state(S_FTP_NO_FILE));
|
||||
return;
|
||||
}
|
||||
conn->from = 0;
|
||||
@ -1019,19 +1024,20 @@ ftp_retr_file(struct socket *socket, struct read_buffer *rb)
|
||||
INTERNAL("WHAT???");
|
||||
}
|
||||
|
||||
ftp_send_retr_req(conn, S_GETH);
|
||||
ftp_send_retr_req(conn, connection_state(S_GETH));
|
||||
return;
|
||||
}
|
||||
|
||||
response = get_ftp_response(conn, rb, 2, NULL);
|
||||
|
||||
if (response == -1) {
|
||||
abort_connection(conn, S_FTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_FTP_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!response) {
|
||||
read_from_socket(conn->socket, rb, S_GETH, ftp_retr_file);
|
||||
read_from_socket(conn->socket, rb, connection_state(S_GETH),
|
||||
ftp_retr_file);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1066,7 +1072,7 @@ ftp_retr_file(struct socket *socket, struct read_buffer *rb)
|
||||
* get_ftp_data_socket would have created the
|
||||
* data_socket without waiting for anything from the
|
||||
* server. */
|
||||
abort_connection(conn, S_FTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_FTP_ERROR));
|
||||
return;
|
||||
}
|
||||
set_handlers(conn->data_socket->fd, (select_handler_T) ftp_data_accept,
|
||||
@ -1084,13 +1090,13 @@ ftp_got_final_response(struct socket *socket, struct read_buffer *rb)
|
||||
int response = get_ftp_response(conn, rb, 0, NULL);
|
||||
|
||||
if (response == -1) {
|
||||
abort_connection(conn, S_FTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_FTP_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!response) {
|
||||
enum connection_state state = conn->state != S_TRANS
|
||||
? S_GETH : conn->state;
|
||||
struct connection_state state = !is_in_state(conn->state, S_TRANS)
|
||||
? connection_state(S_GETH) : conn->state;
|
||||
|
||||
read_from_socket(conn->socket, rb, state, ftp_got_final_response);
|
||||
return;
|
||||
@ -1105,25 +1111,25 @@ ftp_got_final_response(struct socket *socket, struct read_buffer *rb)
|
||||
|
||||
if (!conn->cached
|
||||
|| !redirect_cache(conn->cached, "/", 1, 0)) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
return;
|
||||
}
|
||||
|
||||
if (response >= 400) {
|
||||
abort_connection(conn, S_FTP_FILE_ERROR);
|
||||
abort_connection(conn, connection_state(S_FTP_FILE_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
if (ftp->conn_state == 2) {
|
||||
ftp_end_request(conn, S_OK);
|
||||
ftp_end_request(conn, connection_state(S_OK));
|
||||
} else {
|
||||
ftp->conn_state = 1;
|
||||
if (conn->state != S_TRANS)
|
||||
set_connection_state(conn, S_GETH);
|
||||
if (!is_in_state(conn->state, S_TRANS))
|
||||
set_connection_state(conn, connection_state(S_GETH));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1368,7 +1374,7 @@ ftp_data_accept(struct connection *conn)
|
||||
} else {
|
||||
newsock = accept(conn->data_socket->fd, NULL, NULL);
|
||||
if (newsock < 0) {
|
||||
retry_connection(conn, -errno);
|
||||
retry_connection(conn, connection_state_for_errno(errno));
|
||||
return;
|
||||
}
|
||||
close(conn->data_socket->fd);
|
||||
@ -1404,7 +1410,7 @@ got_something_from_data_connection(struct connection *conn)
|
||||
if (!conn->cached) conn->cached = get_cache_entry(conn->uri);
|
||||
if (!conn->cached) {
|
||||
out_of_mem:
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1421,15 +1427,15 @@ out_of_mem:
|
||||
|
||||
if (ftp->dir && !conn->from) {
|
||||
struct string string;
|
||||
enum connection_state state;
|
||||
struct connection_state state;
|
||||
|
||||
if (!conn->uri->data) {
|
||||
abort_connection(conn, S_FTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_FTP_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
state = init_directory_listing(&string, conn->uri);
|
||||
if (state != S_OK) {
|
||||
if (!is_in_state(state, S_OK)) {
|
||||
abort_connection(conn, state);
|
||||
return;
|
||||
}
|
||||
@ -1452,7 +1458,7 @@ out_of_mem:
|
||||
len = safe_read(conn->data_socket->fd, ftp->ftp_buffer + ftp->buf_pos,
|
||||
FTP_BUF_SIZE - ftp->buf_pos);
|
||||
if (len < 0) {
|
||||
retry_connection(conn, -errno);
|
||||
retry_connection(conn, connection_state_for_errno(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1484,7 +1490,7 @@ out_of_mem:
|
||||
|
||||
}
|
||||
|
||||
set_connection_state(conn, S_TRANS);
|
||||
set_connection_state(conn, connection_state(S_TRANS));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1502,17 +1508,17 @@ out_of_mem:
|
||||
close_socket(conn->data_socket);
|
||||
|
||||
if (ftp->conn_state == 1) {
|
||||
ftp_end_request(conn, S_OK);
|
||||
ftp_end_request(conn, connection_state(S_OK));
|
||||
} else {
|
||||
ftp->conn_state = 2;
|
||||
set_connection_state(conn, S_TRANS);
|
||||
set_connection_state(conn, connection_state(S_TRANS));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ftp_end_request(struct connection *conn, enum connection_state state)
|
||||
ftp_end_request(struct connection *conn, struct connection_state state)
|
||||
{
|
||||
if (state == S_OK && conn->cached) {
|
||||
if (is_in_state(state, S_OK) && conn->cached) {
|
||||
normalize_cache_entry(conn->cached, conn->from);
|
||||
}
|
||||
|
||||
|
@ -197,9 +197,9 @@ add_uri_decoded(struct string *command, unsigned char *string, int length,
|
||||
command->length = strlen(command->source);
|
||||
}
|
||||
|
||||
static enum connection_state init_gopher_index_cache_entry(struct connection *conn);
|
||||
static struct connection_state init_gopher_index_cache_entry(struct connection *conn);
|
||||
|
||||
static enum connection_state
|
||||
static struct connection_state
|
||||
add_gopher_command(struct connection *conn, struct string *command,
|
||||
enum gopher_entity entity,
|
||||
unsigned char *selector, int selectorlen)
|
||||
@ -269,11 +269,11 @@ add_gopher_command(struct connection *conn, struct string *command,
|
||||
return S_CONN;
|
||||
}
|
||||
|
||||
static enum connection_state
|
||||
static struct connection_state
|
||||
init_gopher_connection_info(struct connection *conn)
|
||||
{
|
||||
struct gopher_connection_info *gopher;
|
||||
enum connection_state state;
|
||||
struct connection_state state;
|
||||
struct string command;
|
||||
enum gopher_entity entity = DEFAULT_GOPHER_ENTITY;
|
||||
unsigned char *selector = conn->uri->data;
|
||||
@ -576,15 +576,15 @@ check_gopher_last_line(unsigned char *line, unsigned char *end)
|
||||
}
|
||||
|
||||
/* Parse a Gopher Menu document */
|
||||
static enum connection_state
|
||||
static struct connection_state
|
||||
read_gopher_directory_data(struct connection *conn, struct read_buffer *rb)
|
||||
{
|
||||
enum connection_state state = S_TRANS;
|
||||
struct connection_state state = connection_state(S_TRANS);
|
||||
struct string buffer;
|
||||
unsigned char *end;
|
||||
|
||||
if (conn->from == 0) {
|
||||
enum connection_state state;
|
||||
struct connection_state state;
|
||||
|
||||
state = init_directory_listing(&buffer, conn->uri);
|
||||
if (state != S_OK)
|
||||
@ -645,7 +645,7 @@ init_gopher_cache_entry(struct connection *conn)
|
||||
}
|
||||
|
||||
/* Display a Gopher Index document. */
|
||||
static enum connection_state
|
||||
static struct connection_state
|
||||
init_gopher_index_cache_entry(struct connection *conn)
|
||||
{
|
||||
unsigned char *where;
|
||||
@ -695,7 +695,7 @@ read_gopher_response_data(struct socket *socket, struct read_buffer *rb)
|
||||
{
|
||||
struct connection *conn = socket->conn;
|
||||
struct gopher_connection_info *gopher = conn->info;
|
||||
enum connection_state state = S_TRANS;
|
||||
struct connection_state state = S_TRANS;
|
||||
|
||||
assert(gopher && gopher->entity);
|
||||
|
||||
@ -774,7 +774,7 @@ void
|
||||
gopher_protocol_handler(struct connection *conn)
|
||||
{
|
||||
struct uri *uri = conn->uri;
|
||||
enum connection_state state = S_CONN;
|
||||
struct connection_state state = S_CONN;
|
||||
|
||||
switch (get_uri_port(uri)) {
|
||||
case 105:
|
||||
|
@ -8,6 +8,7 @@ enum blacklist_flags {
|
||||
SERVER_BLACKLIST_NONE = 0,
|
||||
SERVER_BLACKLIST_HTTP10 = 1,
|
||||
SERVER_BLACKLIST_NO_CHARSET = 2,
|
||||
SERVER_BLACKLIST_NO_TLS = 4,
|
||||
};
|
||||
|
||||
void add_blacklist_entry(struct uri *, enum blacklist_flags);
|
||||
|
@ -461,7 +461,7 @@ check_http_server_bugs(struct uri *uri, struct http_connection_info *http,
|
||||
}
|
||||
|
||||
static void
|
||||
http_end_request(struct connection *conn, enum connection_state state,
|
||||
http_end_request(struct connection *conn, struct connection_state state,
|
||||
int notrunc)
|
||||
{
|
||||
struct http_connection_info *http;
|
||||
@ -478,7 +478,7 @@ http_end_request(struct connection *conn, enum connection_state state,
|
||||
&& (!conn->socket->ssl) /* We won't keep alive ssl connections */
|
||||
&& (!get_opt_bool("protocol.http.bugs.post_no_keepalive", NULL)
|
||||
|| !conn->uri->post)) {
|
||||
if (state == S_OK && conn->cached)
|
||||
if (is_in_state(state, S_OK) && conn->cached)
|
||||
normalize_cache_entry(conn->cached, !notrunc ? conn->from : -1);
|
||||
set_connection_state(conn, state);
|
||||
add_keepalive_connection(conn, HTTP_KEEPALIVE_TIMEOUT, NULL);
|
||||
@ -533,7 +533,7 @@ init_http_connection_info(struct connection *conn, int major, int minor, int clo
|
||||
|
||||
http = mem_calloc(1, sizeof(*http));
|
||||
if (!http) {
|
||||
http_end_request(conn, S_OUT_OF_MEM, 0);
|
||||
http_end_request(conn, connection_state(S_OUT_OF_MEM), 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -602,13 +602,13 @@ send_more_post_data(struct socket *socket)
|
||||
struct http_connection_info *http = conn->info;
|
||||
unsigned char buffer[POST_BUFFER_SIZE];
|
||||
int got;
|
||||
enum connection_state error;
|
||||
struct connection_state error;
|
||||
|
||||
got = read_http_post(&http->post, buffer, POST_BUFFER_SIZE, &error);
|
||||
if (got < 0) {
|
||||
http_end_request(conn, error, 0);
|
||||
} else if (got > 0) {
|
||||
write_to_socket(socket, buffer, got, S_TRANS,
|
||||
write_to_socket(socket, buffer, got, connection_state(S_TRANS),
|
||||
send_more_post_data);
|
||||
} else { /* got == 0, meaning end of data */
|
||||
/* Can't use request_from_socket() because there's no
|
||||
@ -617,9 +617,11 @@ send_more_post_data(struct socket *socket)
|
||||
|
||||
socket->state = SOCKET_END_ONCLOSE;
|
||||
if (rb)
|
||||
read_from_socket(socket, rb, S_SENT, http_got_header);
|
||||
read_from_socket(socket, rb, connection_state(S_SENT),
|
||||
http_got_header);
|
||||
else
|
||||
http_end_request(conn, S_OUT_OF_MEM, 0);
|
||||
http_end_request(conn, connection_state(S_OUT_OF_MEM),
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -640,7 +642,7 @@ http_send_header(struct socket *socket)
|
||||
|
||||
/* Sanity check for a host */
|
||||
if (!uri || !uri->host || !*uri->host || !uri->hostlen) {
|
||||
http_end_request(conn, S_BAD_URL, 0);
|
||||
http_end_request(conn, connection_state(S_BAD_URL), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -648,7 +650,7 @@ http_send_header(struct socket *socket)
|
||||
if (!http) return;
|
||||
|
||||
if (!init_string(&header)) {
|
||||
http_end_request(conn, S_OUT_OF_MEM, 0);
|
||||
http_end_request(conn, connection_state(S_OUT_OF_MEM), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -970,7 +972,7 @@ http_send_header(struct socket *socket)
|
||||
* as set by get_form_uri(). This '\n' is dropped if any
|
||||
* and replaced by correct '\r\n' termination here. */
|
||||
unsigned char *postend = strchr(uri->post, '\n');
|
||||
enum connection_state error;
|
||||
struct connection_state error;
|
||||
|
||||
if (postend) {
|
||||
add_to_string(&header, "Content-Type: ");
|
||||
@ -1015,10 +1017,12 @@ http_send_header(struct socket *socket)
|
||||
socket->state = SOCKET_END_ONCLOSE;
|
||||
if (!conn->http_upload_progress && http->post.file_count)
|
||||
conn->http_upload_progress = init_progress(0);
|
||||
write_to_socket(socket, header.source, header.length, S_TRANS,
|
||||
write_to_socket(socket, header.source, header.length,
|
||||
connection_state(S_TRANS),
|
||||
send_more_post_data);
|
||||
} else
|
||||
request_from_socket(socket, header.source, header.length, S_SENT,
|
||||
request_from_socket(socket, header.source, header.length,
|
||||
connection_state(S_SENT),
|
||||
SOCKET_END_ONCLOSE, http_got_header);
|
||||
done_string(&header);
|
||||
}
|
||||
@ -1170,7 +1174,8 @@ static void
|
||||
read_more_http_data(struct connection *conn, struct read_buffer *rb,
|
||||
int already_got_anything)
|
||||
{
|
||||
enum connection_state state = already_got_anything ? S_TRANS : conn->state;
|
||||
struct connection_state state = already_got_anything
|
||||
? connection_state(S_TRANS) : conn->state;
|
||||
|
||||
read_from_socket(conn->socket, rb, state, read_http_data);
|
||||
}
|
||||
@ -1195,7 +1200,7 @@ read_http_data_done(struct connection *conn)
|
||||
}
|
||||
}
|
||||
|
||||
http_end_request(conn, S_OK, 0);
|
||||
http_end_request(conn, connection_state(S_OK), 0);
|
||||
}
|
||||
|
||||
/* Returns:
|
||||
@ -1387,7 +1392,7 @@ read_http_data(struct socket *socket, struct read_buffer *rb)
|
||||
break;
|
||||
default:
|
||||
assertm(ret == -1, "Unexpected return value: %d", ret);
|
||||
abort_connection(conn, S_HTTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_HTTP_ERROR));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1494,7 +1499,9 @@ http_got_header(struct socket *socket, struct read_buffer *rb)
|
||||
unsigned char *d;
|
||||
struct uri *uri = conn->proxied_uri; /* Set to the real uri */
|
||||
struct http_version version = { 0, 9 };
|
||||
enum connection_state state = (conn->state != S_PROC ? S_GETH : S_PROC);
|
||||
struct connection_state state = (!is_in_state(conn->state, S_PROC)
|
||||
? connection_state(S_GETH)
|
||||
: connection_state(S_PROC));
|
||||
int a, h = 200;
|
||||
int cf;
|
||||
|
||||
@ -1507,7 +1514,7 @@ http_got_header(struct socket *socket, struct read_buffer *rb)
|
||||
conn->tries = -1;
|
||||
}
|
||||
}
|
||||
retry_connection(conn, S_CANT_READ);
|
||||
retry_connection(conn, connection_state(S_CANT_READ));
|
||||
return;
|
||||
}
|
||||
socket->state = SOCKET_RETRY_ONCLOSE;
|
||||
@ -1515,7 +1522,7 @@ http_got_header(struct socket *socket, struct read_buffer *rb)
|
||||
again:
|
||||
a = get_header(rb);
|
||||
if (a == -1) {
|
||||
abort_connection(conn, S_HTTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_HTTP_ERROR));
|
||||
return;
|
||||
}
|
||||
if (!a) {
|
||||
@ -1528,7 +1535,7 @@ again:
|
||||
if (a == -2) a = 0;
|
||||
if ((a && get_http_code(rb, &h, &version))
|
||||
|| h == 101) {
|
||||
abort_connection(conn, S_HTTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_HTTP_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1541,13 +1548,13 @@ again:
|
||||
head = (a ? memacpy(rb->data, a)
|
||||
: stracpy("\r\nContent-Type: text/html\r\n"));
|
||||
if (!head) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
if (check_http_server_bugs(uri, http, head)) {
|
||||
mem_free(head);
|
||||
retry_connection(conn, S_RESTART);
|
||||
retry_connection(conn, connection_state(S_RESTART));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1566,7 +1573,7 @@ again:
|
||||
if (h2 >= 100 && h2 < 600) h = h2;
|
||||
if (h == 101) {
|
||||
mem_free(head);
|
||||
abort_connection(conn, S_HTTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_HTTP_ERROR));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1584,23 +1591,23 @@ again:
|
||||
|
||||
if (h == 100) {
|
||||
mem_free(head);
|
||||
state = S_PROC;
|
||||
state = connection_state(S_PROC);
|
||||
kill_buffer_data(rb, a);
|
||||
goto again;
|
||||
}
|
||||
if (h < 200) {
|
||||
mem_free(head);
|
||||
abort_connection(conn, S_HTTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_HTTP_ERROR));
|
||||
return;
|
||||
}
|
||||
if (h == 304) {
|
||||
mem_free(head);
|
||||
http_end_request(conn, S_OK, 1);
|
||||
http_end_request(conn, connection_state(S_OK), 1);
|
||||
return;
|
||||
}
|
||||
if (h == 204) {
|
||||
mem_free(head);
|
||||
http_end_request(conn, S_HTTP_204, 0);
|
||||
http_end_request(conn, connection_state(S_HTTP_204), 0);
|
||||
return;
|
||||
}
|
||||
if (h == 200 && connection_is_https_proxy(conn) && !conn->socket->ssl) {
|
||||
@ -1609,7 +1616,7 @@ again:
|
||||
socket->need_ssl = 1;
|
||||
complete_connect_socket(socket, uri, http_send_header);
|
||||
#else
|
||||
abort_connection(conn, S_SSL_ERROR);
|
||||
abort_connection(conn, connection_state(S_SSL_ERROR));
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
@ -1617,7 +1624,7 @@ again:
|
||||
conn->cached = get_cache_entry(conn->uri);
|
||||
if (!conn->cached) {
|
||||
mem_free(head);
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
conn->cached->cgi = conn->cgi;
|
||||
@ -1711,7 +1718,7 @@ again:
|
||||
if (h == 401) {
|
||||
if (check_http_authentication(conn, uri,
|
||||
conn->cached->head, "WWW-Authenticate")) {
|
||||
retry_connection(conn, S_RESTART);
|
||||
retry_connection(conn, connection_state(S_RESTART));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1784,7 +1791,7 @@ again:
|
||||
if ((conn->progress->start <= 0 && conn->from > cf) || conn->from < 0) {
|
||||
/* We don't want this if conn->progress.start because then conn->from will
|
||||
* be probably value of conn->progress.start, while cf is 0. */
|
||||
abort_connection(conn, S_HTTP_ERROR);
|
||||
abort_connection(conn, connection_state(S_HTTP_ERROR));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1851,7 +1858,7 @@ again:
|
||||
if (conn->from) {
|
||||
conn->from = 0;
|
||||
mem_free(d);
|
||||
retry_connection(conn, S_MODIFIED);
|
||||
retry_connection(conn, connection_state(S_MODIFIED));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1883,7 +1890,7 @@ again:
|
||||
if (conn->from) {
|
||||
conn->from = 0;
|
||||
mem_free(d);
|
||||
retry_connection(conn, S_MODIFIED);
|
||||
retry_connection(conn, connection_state(S_MODIFIED));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ done_http_post(struct http_post *http_post)
|
||||
* @relates http_post */
|
||||
int
|
||||
open_http_post(struct http_post *http_post, const unsigned char *post_data,
|
||||
enum connection_state *error)
|
||||
struct connection_state *error)
|
||||
{
|
||||
off_t size = 0;
|
||||
size_t length = strlen(post_data);
|
||||
@ -111,13 +111,13 @@ open_http_post(struct http_post *http_post, const unsigned char *post_data,
|
||||
filename = memacpy(begin + 1, end - begin - 1); /* adds '\0' */
|
||||
if (!filename) {
|
||||
done_http_post(http_post);
|
||||
*error = S_OUT_OF_MEM;
|
||||
*error = connection_state(S_OUT_OF_MEM);
|
||||
return 0;
|
||||
}
|
||||
decode_uri(filename);
|
||||
res = stat(filename, &sb);
|
||||
if (res) {
|
||||
*error = -errno;
|
||||
*error = connection_state_for_errno(errno);
|
||||
done_http_post(http_post);
|
||||
return 0;
|
||||
}
|
||||
@ -131,7 +131,7 @@ open_http_post(struct http_post *http_post, const unsigned char *post_data,
|
||||
if (new_files == NULL) {
|
||||
mem_free(filename);
|
||||
done_http_post(http_post);
|
||||
*error = S_OUT_OF_MEM;
|
||||
*error = connection_state(S_OUT_OF_MEM);
|
||||
return 0;
|
||||
}
|
||||
http_post->files = new_files;
|
||||
@ -157,14 +157,14 @@ open_http_post(struct http_post *http_post, const unsigned char *post_data,
|
||||
static int
|
||||
read_http_post_inline(struct http_post *http_post,
|
||||
unsigned char buffer[], int max,
|
||||
enum connection_state *error)
|
||||
struct connection_state *error)
|
||||
{
|
||||
const unsigned char *post = http_post->post_data;
|
||||
const unsigned char *end = strchr(post, FILE_CHAR);
|
||||
int total = 0;
|
||||
|
||||
assert(http_post->post_fd < 0);
|
||||
if_assert_failed { *error = S_INTERNAL; return -1; }
|
||||
if_assert_failed { *error = connection_state(S_INTERNAL); return -1; }
|
||||
|
||||
if (!end)
|
||||
end = strchr(post, '\0');
|
||||
@ -199,7 +199,7 @@ read_http_post_inline(struct http_post *http_post,
|
||||
if (total > 0)
|
||||
return total; /* retry the open on the next call */
|
||||
else {
|
||||
*error = -errno;
|
||||
*error = connection_state_for_errno(errno);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -215,7 +215,7 @@ read_http_post_inline(struct http_post *http_post,
|
||||
static int
|
||||
read_http_post_fd(struct http_post *http_post,
|
||||
unsigned char buffer[], int max,
|
||||
enum connection_state *error)
|
||||
struct connection_state *error)
|
||||
{
|
||||
const struct http_post_file *const file
|
||||
= &http_post->files[http_post->file_index];
|
||||
@ -224,7 +224,7 @@ read_http_post_fd(struct http_post *http_post,
|
||||
/* safe_read() would set errno = EBADF anyway, but check this
|
||||
* explicitly to make any such bugs easier to detect. */
|
||||
assert(http_post->post_fd >= 0);
|
||||
if_assert_failed { *error = S_INTERNAL; return -1; }
|
||||
if_assert_failed { *error = connection_state(S_INTERNAL); return -1; }
|
||||
|
||||
ret = safe_read(http_post->post_fd, buffer, max);
|
||||
if (ret <= 0) {
|
||||
@ -237,7 +237,7 @@ read_http_post_fd(struct http_post *http_post,
|
||||
* It will be cleared when the next file is opened. */
|
||||
|
||||
if (ret == -1) {
|
||||
*error = -errno_from_read;
|
||||
*error = connection_state_for_errno(errno_from_read);
|
||||
return -1;
|
||||
} else if (http_post->file_read != file->size) {
|
||||
/* ELinks already sent a Content-Length header
|
||||
@ -247,7 +247,7 @@ read_http_post_fd(struct http_post *http_post,
|
||||
* enough data to fill the Content-Length.
|
||||
* (Well, it could pad with zeroes, but that
|
||||
* would be just weird.) */
|
||||
*error = S_HTTP_UPLOAD_RESIZED;
|
||||
*error = connection_state(S_HTTP_UPLOAD_RESIZED);
|
||||
return -1;
|
||||
} else {
|
||||
/* The upload file ended but there may still
|
||||
@ -265,7 +265,7 @@ read_http_post_fd(struct http_post *http_post,
|
||||
* been extended. Abort the connection because ELinks
|
||||
* can no longer fit the entire file in the original
|
||||
* Content-Length. */
|
||||
*error = S_HTTP_UPLOAD_RESIZED;
|
||||
*error = connection_state(S_HTTP_UPLOAD_RESIZED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -282,7 +282,7 @@ read_http_post_fd(struct http_post *http_post,
|
||||
int
|
||||
read_http_post(struct http_post *http_post,
|
||||
unsigned char buffer[], int max,
|
||||
enum connection_state *error)
|
||||
struct connection_state *error)
|
||||
{
|
||||
int total = 0;
|
||||
|
||||
|
@ -55,9 +55,9 @@ struct http_post {
|
||||
void init_http_post(struct http_post *http_post);
|
||||
void done_http_post(struct http_post *http_post);
|
||||
int open_http_post(struct http_post *http_post, const unsigned char *post_data,
|
||||
enum connection_state *error);
|
||||
struct connection_state *error);
|
||||
int read_http_post(struct http_post *http_post,
|
||||
unsigned char buffer[], int max,
|
||||
enum connection_state *error);
|
||||
struct connection_state *error);
|
||||
|
||||
#endif
|
||||
|
@ -106,13 +106,13 @@ init_nntp_connection_info(struct connection *conn)
|
||||
assert(conn->info == NULL);
|
||||
assert(conn->done == NULL);
|
||||
if_assert_failed {
|
||||
abort_connection(conn, S_INTERNAL);
|
||||
abort_connection(conn, connection_state(S_INTERNAL));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nntp = mem_calloc(1, sizeof(*nntp));
|
||||
if (!nntp) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -150,7 +150,7 @@ init_nntp_connection_info(struct connection *conn)
|
||||
break;
|
||||
|
||||
/* FIXME: Special S_NNTP_BAD_RANGE */
|
||||
abort_connection(conn, S_BAD_URL);
|
||||
abort_connection(conn, connection_state(S_BAD_URL));
|
||||
return NULL;
|
||||
|
||||
case NNTP_TARGET_ARTICLE_NUMBER:
|
||||
@ -164,12 +164,12 @@ init_nntp_connection_info(struct connection *conn)
|
||||
/* Map nntp://<server>/<group> to nntp://<server>/<group>/ so
|
||||
* we get only one cache entry with content. */
|
||||
if (!groupend) {
|
||||
enum connection_state state = S_OK;
|
||||
struct connection_state state = connection_state(S_OK);
|
||||
|
||||
conn->cached = get_cache_entry(conn->uri);
|
||||
if (!conn->cached
|
||||
|| !redirect_cache(conn->cached, "/", 0, 0))
|
||||
state = S_OUT_OF_MEM;
|
||||
state = connection_state(S_OUT_OF_MEM);
|
||||
|
||||
abort_connection(conn, state);
|
||||
return NULL;
|
||||
@ -177,7 +177,7 @@ init_nntp_connection_info(struct connection *conn)
|
||||
|
||||
/* Reject nntp://<server>/<group>/<group> */
|
||||
if (nntp->group.source) {
|
||||
abort_connection(conn, S_BAD_URL);
|
||||
abort_connection(conn, connection_state(S_BAD_URL));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -204,13 +204,13 @@ nntp_quit(struct connection *conn)
|
||||
assert(conn->info == NULL);
|
||||
assert(conn->done == NULL);
|
||||
if_assert_failed {
|
||||
abort_connection(conn, S_INTERNAL);
|
||||
abort_connection(conn, connection_state(S_INTERNAL));
|
||||
return;
|
||||
}
|
||||
|
||||
info = mem_calloc(1, sizeof(*info));
|
||||
if (!info) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -222,7 +222,7 @@ nntp_quit(struct connection *conn)
|
||||
}
|
||||
|
||||
static void
|
||||
nntp_end_request(struct connection *conn, enum connection_state state)
|
||||
nntp_end_request(struct connection *conn, struct connection_state state)
|
||||
{
|
||||
struct nntp_connection_info *nntp = conn->info;
|
||||
|
||||
@ -231,11 +231,11 @@ nntp_end_request(struct connection *conn, enum connection_state state)
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == S_OK) {
|
||||
if (is_in_state(state, S_OK)) {
|
||||
if (conn->cached) {
|
||||
normalize_cache_entry(conn->cached, conn->from);
|
||||
}
|
||||
} else if (state == S_OUT_OF_MEM) {
|
||||
} else if (is_in_state(state, S_OUT_OF_MEM)) {
|
||||
/* FIXME: Clear the socket buffers before ending so the one
|
||||
* grabing the keepalive connection will be able to go on. */
|
||||
}
|
||||
@ -253,38 +253,39 @@ read_nntp_data(struct socket *socket, struct read_buffer *rb)
|
||||
struct connection *conn = socket->conn;
|
||||
|
||||
if (socket->state == SOCKET_CLOSED) {
|
||||
nntp_end_request(conn, S_OK);
|
||||
nntp_end_request(conn, connection_state(S_OK));
|
||||
return;
|
||||
}
|
||||
|
||||
switch (read_nntp_response_data(conn, rb)) {
|
||||
switch (read_nntp_response_data(conn, rb).basic) {
|
||||
case S_OK:
|
||||
nntp_send_command(conn);
|
||||
break;
|
||||
|
||||
case S_OUT_OF_MEM:
|
||||
nntp_end_request(conn, S_OUT_OF_MEM);
|
||||
nntp_end_request(conn, connection_state(S_OUT_OF_MEM));
|
||||
break;
|
||||
|
||||
case S_TRANS:
|
||||
default:
|
||||
read_from_socket(conn->socket, rb, S_TRANS, read_nntp_data);
|
||||
read_from_socket(conn->socket, rb, connection_state(S_TRANS),
|
||||
read_nntp_data);
|
||||
}
|
||||
}
|
||||
|
||||
/* Translate NNTP code to the internal connection state. */
|
||||
static enum connection_state
|
||||
static struct connection_state
|
||||
get_nntp_connection_state(enum nntp_code code)
|
||||
{
|
||||
switch (code) {
|
||||
case NNTP_CODE_400_GOODBYE: return S_NNTP_SERVER_HANG_UP;
|
||||
case NNTP_CODE_411_GROUP_UNKNOWN: return S_NNTP_GROUP_UNKNOWN;
|
||||
case NNTP_CODE_423_ARTICLE_NONUMBER: return S_NNTP_ARTICLE_UNKNOWN;
|
||||
case NNTP_CODE_430_ARTICLE_NOID: return S_NNTP_ARTICLE_UNKNOWN;
|
||||
case NNTP_CODE_436_ARTICLE_TRANSFER: return S_NNTP_TRANSFER_ERROR;
|
||||
case NNTP_CODE_480_AUTH_REQUIRED: return S_NNTP_AUTH_REQUIRED;
|
||||
case NNTP_CODE_502_ACCESS_DENIED: return S_NNTP_ACCESS_DENIED;
|
||||
case NNTP_CODE_503_PROGRAM_FAULT: return S_NNTP_SERVER_ERROR;
|
||||
case NNTP_CODE_400_GOODBYE: return connection_state(S_NNTP_SERVER_HANG_UP);
|
||||
case NNTP_CODE_411_GROUP_UNKNOWN: return connection_state(S_NNTP_GROUP_UNKNOWN);
|
||||
case NNTP_CODE_423_ARTICLE_NONUMBER: return connection_state(S_NNTP_ARTICLE_UNKNOWN);
|
||||
case NNTP_CODE_430_ARTICLE_NOID: return connection_state(S_NNTP_ARTICLE_UNKNOWN);
|
||||
case NNTP_CODE_436_ARTICLE_TRANSFER: return connection_state(S_NNTP_TRANSFER_ERROR);
|
||||
case NNTP_CODE_480_AUTH_REQUIRED: return connection_state(S_NNTP_AUTH_REQUIRED);
|
||||
case NNTP_CODE_502_ACCESS_DENIED: return connection_state(S_NNTP_ACCESS_DENIED);
|
||||
case NNTP_CODE_503_PROGRAM_FAULT: return connection_state(S_NNTP_SERVER_ERROR);
|
||||
|
||||
case NNTP_CODE_412_GROUP_UNSET:
|
||||
case NNTP_CODE_420_ARTICLE_UNSET:
|
||||
@ -301,7 +302,7 @@ get_nntp_connection_state(enum nntp_code code)
|
||||
default:
|
||||
/* Notice and error codes for stuff which is either not
|
||||
* supported or which is not supposed to happen. */
|
||||
return S_NNTP_ERROR;
|
||||
return connection_state(S_NNTP_ERROR);
|
||||
};
|
||||
}
|
||||
|
||||
@ -312,7 +313,7 @@ nntp_got_response(struct socket *socket, struct read_buffer *rb)
|
||||
struct nntp_connection_info *nntp = conn->info;
|
||||
|
||||
if (socket->state == SOCKET_CLOSED) {
|
||||
nntp_end_request(conn, S_OK);
|
||||
nntp_end_request(conn, connection_state(S_OK));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -320,11 +321,12 @@ nntp_got_response(struct socket *socket, struct read_buffer *rb)
|
||||
|
||||
switch (nntp->code) {
|
||||
case NNTP_CODE_NONE:
|
||||
read_from_socket(conn->socket, rb, S_TRANS, nntp_got_response);
|
||||
read_from_socket(conn->socket, rb, connection_state(S_TRANS),
|
||||
nntp_got_response);
|
||||
break;
|
||||
|
||||
case NNTP_CODE_INVALID:
|
||||
nntp_end_request(conn, S_NNTP_ERROR);
|
||||
nntp_end_request(conn, connection_state(S_NNTP_ERROR));
|
||||
break;
|
||||
|
||||
case NNTP_CODE_200_HELLO:
|
||||
@ -334,7 +336,7 @@ nntp_got_response(struct socket *socket, struct read_buffer *rb)
|
||||
break;
|
||||
|
||||
case NNTP_CODE_205_GOODBYE:
|
||||
nntp_end_request(conn, S_OK);
|
||||
nntp_end_request(conn, connection_state(S_OK));
|
||||
break;
|
||||
|
||||
case NNTP_CODE_215_FOLLOW_GROUPS:
|
||||
@ -523,19 +525,20 @@ nntp_send_command(struct connection *conn)
|
||||
nntp->command = get_nntp_command(nntp);
|
||||
|
||||
if (nntp->command == NNTP_COMMAND_NONE) {
|
||||
nntp_end_request(conn, S_OK);
|
||||
nntp_end_request(conn, connection_state(S_OK));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!init_string(&req)) {
|
||||
nntp_end_request(conn, S_OUT_OF_MEM);
|
||||
nntp_end_request(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
/* FIXME: Check non empty and < NNTP_MAX_COMMAND_LENGTH */
|
||||
add_nntp_command_to_string(&req, nntp);
|
||||
|
||||
request_from_socket(conn->socket, req.source, req.length, S_SENT,
|
||||
request_from_socket(conn->socket, req.source, req.length,
|
||||
connection_state(S_SENT),
|
||||
SOCKET_END_ONCLOSE, nntp_got_response);
|
||||
done_string(&req);
|
||||
}
|
||||
@ -581,13 +584,13 @@ news_protocol_handler(struct connection *conn)
|
||||
|
||||
if (!*server) server = getenv("NNTPSERVER");
|
||||
if (!server || !*server) {
|
||||
abort_connection(conn, S_NNTP_NEWS_SERVER);
|
||||
abort_connection(conn, connection_state(S_NNTP_NEWS_SERVER));
|
||||
return;
|
||||
}
|
||||
|
||||
conn->cached = get_cache_entry(conn->uri);
|
||||
if (!conn->cached || !init_string(&location)) {
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -600,5 +603,5 @@ news_protocol_handler(struct connection *conn)
|
||||
|
||||
done_string(&location);
|
||||
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
}
|
||||
|
@ -89,14 +89,14 @@ get_nntp_message_header_end(unsigned char *data, int datalen)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static enum connection_state
|
||||
static struct connection_state
|
||||
init_nntp_header(struct connection *conn, struct read_buffer *rb)
|
||||
{
|
||||
struct nntp_connection_info *nntp = conn->info;
|
||||
|
||||
if (!conn->cached) {
|
||||
conn->cached = get_cache_entry(conn->uri);
|
||||
if (!conn->cached) return S_OUT_OF_MEM;
|
||||
if (!conn->cached) return connection_state(S_OUT_OF_MEM);
|
||||
|
||||
} else if (conn->cached->head || conn->cached->content_type) {
|
||||
/* If the head is set wipe out the content to be sure */
|
||||
@ -107,7 +107,7 @@ init_nntp_header(struct connection *conn, struct read_buffer *rb)
|
||||
/* XXX: Override any Content-Type line in the header */
|
||||
mem_free_set(&conn->cached->content_type, stracpy("text/html"));
|
||||
if (!conn->cached->content_type)
|
||||
return S_OUT_OF_MEM;
|
||||
return connection_state(S_OUT_OF_MEM);
|
||||
|
||||
switch (nntp->target) {
|
||||
case NNTP_TARGET_ARTICLE_NUMBER:
|
||||
@ -119,12 +119,12 @@ init_nntp_header(struct connection *conn, struct read_buffer *rb)
|
||||
end = get_nntp_message_header_end(rb->data, rb->length);
|
||||
if (!end) {
|
||||
/* Redo the whole cache entry thing next time */
|
||||
return S_TRANS;
|
||||
return connection_state(S_TRANS);
|
||||
}
|
||||
|
||||
/* FIXME: Add the NNTP response code line */
|
||||
conn->cached->head = stracpy("FIXME NNTP response code\r\n");
|
||||
if (!conn->cached->head) return S_OUT_OF_MEM;
|
||||
if (!conn->cached->head) return connection_state(S_OUT_OF_MEM);
|
||||
|
||||
add_to_strn(&conn->cached->head, rb->data);
|
||||
|
||||
@ -140,7 +140,7 @@ init_nntp_header(struct connection *conn, struct read_buffer *rb)
|
||||
break;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
return connection_state(S_OK);
|
||||
}
|
||||
|
||||
|
||||
@ -462,31 +462,31 @@ add_nntp_html_line(struct string *html, struct connection *conn,
|
||||
add_char_to_string(html, '\n');
|
||||
}
|
||||
|
||||
enum connection_state
|
||||
struct connection_state
|
||||
read_nntp_response_data(struct connection *conn, struct read_buffer *rb)
|
||||
{
|
||||
struct string html;
|
||||
unsigned char *end;
|
||||
enum connection_state state = S_TRANS;
|
||||
struct connection_state state = connection_state(S_TRANS);
|
||||
|
||||
if (conn->from == 0) {
|
||||
switch (init_nntp_header(conn, rb)) {
|
||||
switch (init_nntp_header(conn, rb).basic) {
|
||||
case S_OK:
|
||||
break;
|
||||
|
||||
case S_OUT_OF_MEM:
|
||||
return S_OUT_OF_MEM;
|
||||
return connection_state(S_OUT_OF_MEM);
|
||||
|
||||
case S_TRANS:
|
||||
return S_TRANS;
|
||||
return connection_state(S_TRANS);
|
||||
|
||||
default:
|
||||
return S_NNTP_ERROR;
|
||||
return connection_state(S_NNTP_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (!init_string(&html))
|
||||
return S_OUT_OF_MEM;
|
||||
return connection_state(S_OUT_OF_MEM);
|
||||
|
||||
if (conn->from == 0)
|
||||
add_nntp_html_start(&html, conn);
|
||||
@ -495,7 +495,7 @@ read_nntp_response_data(struct connection *conn, struct read_buffer *rb)
|
||||
unsigned char *line = check_nntp_line(rb->data, end);
|
||||
|
||||
if (!line) {
|
||||
state = S_OK;
|
||||
state = connection_state(S_OK);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -505,7 +505,7 @@ read_nntp_response_data(struct connection *conn, struct read_buffer *rb)
|
||||
kill_buffer_data(rb, end - rb->data);
|
||||
}
|
||||
|
||||
if (state != S_TRANS)
|
||||
if (!is_in_state(state, S_TRANS))
|
||||
add_nntp_html_end(&html, conn);
|
||||
|
||||
add_fragment(conn->cached, conn->from, html.source, html.length);
|
||||
|
@ -13,7 +13,7 @@ struct read_buffer;
|
||||
* S_TRANS (transferring) means 'end-of-text' not reached yet
|
||||
* S_OK means no more text expected
|
||||
* S_OUT_OF_MEM allocation failure of some sort */
|
||||
enum connection_state
|
||||
struct connection_state
|
||||
read_nntp_response_data(struct connection *conn, struct read_buffer *rb);
|
||||
|
||||
/* Reads the first line in the NNTP response from the @rb read buffer and
|
||||
|
@ -212,7 +212,7 @@ static void
|
||||
generic_external_protocol_handler(struct session *ses, struct uri *uri)
|
||||
{
|
||||
/* [gettext_accelerator_context(generic_external_protocol_handler)] */
|
||||
enum connection_state state;
|
||||
struct connection_state state;
|
||||
|
||||
switch (uri->protocol) {
|
||||
case PROTOCOL_JAVASCRIPT:
|
||||
@ -220,18 +220,18 @@ generic_external_protocol_handler(struct session *ses, struct uri *uri)
|
||||
ecmascript_protocol_handler(ses, uri);
|
||||
return;
|
||||
#else
|
||||
state = S_NO_JAVASCRIPT;
|
||||
state = connection_state(S_NO_JAVASCRIPT);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case PROTOCOL_UNKNOWN:
|
||||
state = S_UNKNOWN_PROTOCOL;
|
||||
state = connection_state(S_UNKNOWN_PROTOCOL);
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifndef CONFIG_SSL
|
||||
if (get_protocol_need_ssl(uri->protocol)) {
|
||||
state = S_SSL_ERROR;
|
||||
state = connection_state(S_SSL_ERROR);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
@ -55,7 +55,7 @@ proxy_probe_no_proxy(unsigned char *url, unsigned char *no_proxy)
|
||||
|
||||
static struct uri *
|
||||
proxy_uri(struct uri *uri, unsigned char *proxy,
|
||||
enum connection_state *connection_state)
|
||||
struct connection_state *error_state)
|
||||
{
|
||||
struct string string;
|
||||
|
||||
@ -70,10 +70,10 @@ proxy_uri(struct uri *uri, unsigned char *proxy,
|
||||
/* XXX: Assume the problem is due to @proxy having bad format.
|
||||
* This is a lot faster easier than checking the format. */
|
||||
if (!uri)
|
||||
*connection_state = S_PROXY_ERROR;
|
||||
*error_state = connection_state(S_PROXY_ERROR);
|
||||
} else {
|
||||
uri = NULL;
|
||||
*connection_state = S_OUT_OF_MEM;
|
||||
*error_state = connection_state(S_OUT_OF_MEM);
|
||||
}
|
||||
|
||||
done_string(&string);
|
||||
@ -118,7 +118,7 @@ get_protocol_proxy(unsigned char *opt,
|
||||
|
||||
static struct uri *
|
||||
get_proxy_worker(struct uri *uri, unsigned char *proxy,
|
||||
enum connection_state *connection_state)
|
||||
struct connection_state *error_state)
|
||||
{
|
||||
unsigned char *protocol_proxy = NULL;
|
||||
|
||||
@ -126,7 +126,7 @@ get_proxy_worker(struct uri *uri, unsigned char *proxy,
|
||||
if (*proxy) {
|
||||
proxy = strip_proxy_protocol(proxy, "http://", "ftp://");
|
||||
|
||||
return proxy_uri(uri, proxy, connection_state);
|
||||
return proxy_uri(uri, proxy, error_state);
|
||||
}
|
||||
|
||||
/* "" from script_hook_get_proxy() */
|
||||
@ -177,14 +177,14 @@ get_proxy_worker(struct uri *uri, unsigned char *proxy,
|
||||
if (!no_proxy || !*no_proxy) no_proxy = getenv("no_proxy");
|
||||
|
||||
if (!proxy_probe_no_proxy(uri->host, no_proxy))
|
||||
return proxy_uri(uri, protocol_proxy, connection_state);
|
||||
return proxy_uri(uri, protocol_proxy, error_state);
|
||||
}
|
||||
|
||||
return get_composed_uri(uri, URI_BASE);
|
||||
}
|
||||
|
||||
struct uri *
|
||||
get_proxy_uri(struct uri *uri, enum connection_state *connection_state)
|
||||
get_proxy_uri(struct uri *uri, struct connection_state *error_state)
|
||||
{
|
||||
if (uri->protocol == PROTOCOL_PROXY) {
|
||||
return get_composed_uri(uri, URI_BASE);
|
||||
@ -196,11 +196,11 @@ get_proxy_uri(struct uri *uri, enum connection_state *connection_state)
|
||||
set_event_id(get_proxy_event_id, "get-proxy");
|
||||
trigger_event(get_proxy_event_id, &tmp, struri(uri));
|
||||
|
||||
uri = get_proxy_worker(uri, tmp, connection_state);
|
||||
uri = get_proxy_worker(uri, tmp, error_state);
|
||||
mem_free_if(tmp);
|
||||
return uri;
|
||||
#else
|
||||
return get_proxy_worker(uri, NULL, connection_state);
|
||||
return get_proxy_worker(uri, NULL, error_state);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
#ifndef EL__PROTOCOL_PROXY_H
|
||||
#define EL__PROTOCOL_PROXY_H
|
||||
|
||||
enum connection_state;
|
||||
struct connection_state;
|
||||
struct uri;
|
||||
|
||||
/* Checks if the passed URI has been configured to go through a proxy. The
|
||||
* fragment is removed from the returned URI. */
|
||||
/* If @connection_state is non-NULL it will be set to indicate what error
|
||||
* occurred if the function returns NULL. */
|
||||
struct uri *get_proxy_uri(struct uri *uri, enum connection_state *connection_state);
|
||||
struct uri *get_proxy_uri(struct uri *uri, struct connection_state *connection_state);
|
||||
|
||||
/* ``Translates'' the passed URI into the URI being proxied. If it is not a
|
||||
* proxy:// URI it will return the URI with the fragment removed. */
|
||||
|
@ -71,10 +71,13 @@ static FILE *header_out, *data_out;
|
||||
* process, and it would be very cumbersome to free those. */
|
||||
|
||||
static void
|
||||
smb_error(int error)
|
||||
smb_error(struct connection_state error)
|
||||
{
|
||||
if (is_system_error(error))
|
||||
fprintf(data_out, "S%d\n", (int) error.syserr);
|
||||
else
|
||||
fprintf(data_out, "I%d\n", (int) error.basic);
|
||||
fputs("text/x-error", header_out);
|
||||
fprintf(data_out, "%d\n", error);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -252,8 +255,8 @@ smb_directory(int dir, struct uri *uri)
|
||||
struct string buf;
|
||||
unsigned char dircolor[8] = "";
|
||||
|
||||
if (init_directory_listing(&buf, uri) != S_OK) {
|
||||
smb_error(-S_OUT_OF_MEM);
|
||||
if (!is_in_state(init_directory_listing(&buf, uri), S_OK)) {
|
||||
smb_error(connection_state(S_OUT_OF_MEM));
|
||||
}
|
||||
|
||||
fputs("text/html", header_out);
|
||||
@ -297,7 +300,7 @@ do_smb(struct connection *conn)
|
||||
unsigned char *uri_string = get_uri_string(uri, URI_HOST | URI_PORT | URI_DATA);
|
||||
|
||||
if (!uri_string || !init_string(&string)) {
|
||||
smb_error(-S_OUT_OF_MEM);
|
||||
smb_error(connection_state(S_OUT_OF_MEM));
|
||||
}
|
||||
/* Must URI-encode the username and password to avoid
|
||||
* ambiguity if they contain "/:@" characters.
|
||||
@ -320,10 +323,10 @@ do_smb(struct connection *conn)
|
||||
}
|
||||
|
||||
if (!url) {
|
||||
smb_error(-S_OUT_OF_MEM);
|
||||
smb_error(connection_state(S_OUT_OF_MEM));
|
||||
}
|
||||
if (smbc_init(smb_auth, 0)) {
|
||||
smb_error(errno);
|
||||
smb_error(connection_state_for_errno(errno));
|
||||
};
|
||||
|
||||
dir = smbc_opendir(url);
|
||||
@ -345,12 +348,12 @@ do_smb(struct connection *conn)
|
||||
* for credentials. */
|
||||
if (errno == ENOENT && errno_from_opendir == EACCES)
|
||||
errno = errno_from_opendir;
|
||||
smb_error(errno);
|
||||
smb_error(connection_state_for_errno(errno));
|
||||
}
|
||||
|
||||
res = smbc_fstat(file, &sb);
|
||||
if (res) {
|
||||
smb_error(res);
|
||||
smb_error(connection_state_for_errno(res));
|
||||
}
|
||||
/* filesize */
|
||||
fprintf(header_out, "%" OFF_PRINT_FORMAT,
|
||||
@ -375,7 +378,7 @@ static void
|
||||
prompt_username_pw(struct connection *conn)
|
||||
{
|
||||
add_auth_entry(conn->uri, "Samba", NULL, NULL, 0);
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -383,10 +386,10 @@ smb_got_error(struct socket *socket, struct read_buffer *rb)
|
||||
{
|
||||
int len = rb->length;
|
||||
struct connection *conn = socket->conn;
|
||||
int error;
|
||||
struct connection_state error;
|
||||
|
||||
if (len < 0) {
|
||||
abort_connection(conn, -errno);
|
||||
abort_connection(conn, connection_state_for_errno(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -396,20 +399,28 @@ smb_got_error(struct socket *socket, struct read_buffer *rb)
|
||||
* pipe. */
|
||||
assert(rb->freespace >= 1);
|
||||
if_assert_failed {
|
||||
abort_connection(conn, S_INTERNAL);
|
||||
abort_connection(conn, connection_state(S_INTERNAL));
|
||||
return;
|
||||
}
|
||||
rb->data[len] = '\0';
|
||||
error = atoi(rb->data);
|
||||
kill_buffer_data(rb, len);
|
||||
switch (error) {
|
||||
case EACCES:
|
||||
prompt_username_pw(conn);
|
||||
switch (rb->data[0]) {
|
||||
case 'S':
|
||||
error = connection_state_for_errno(atoi(rb->data + 1));
|
||||
break;
|
||||
case 'I':
|
||||
error = connection_state(atoi(rb->data + 1));
|
||||
break;
|
||||
default:
|
||||
abort_connection(conn, -error);
|
||||
ERROR("malformed error code: %s", rb->data);
|
||||
error = connection_state(S_INTERNAL);
|
||||
break;
|
||||
}
|
||||
kill_buffer_data(rb, len);
|
||||
|
||||
if (is_system_error(error) && error.syserr == EACCES)
|
||||
prompt_username_pw(conn);
|
||||
else
|
||||
abort_connection(conn, error);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -419,12 +430,12 @@ smb_got_data(struct socket *socket, struct read_buffer *rb)
|
||||
struct connection *conn = socket->conn;
|
||||
|
||||
if (len < 0) {
|
||||
abort_connection(conn, -errno);
|
||||
abort_connection(conn, connection_state_for_errno(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!len) {
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -435,7 +446,7 @@ smb_got_data(struct socket *socket, struct read_buffer *rb)
|
||||
conn->from += len;
|
||||
kill_buffer_data(rb, len);
|
||||
|
||||
read_from_socket(socket, rb, S_TRANS, smb_got_data);
|
||||
read_from_socket(socket, rb, connection_state(S_TRANS), smb_got_data);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -454,7 +465,7 @@ smb_got_header(struct socket *socket, struct read_buffer *rb)
|
||||
* and assume abort_connection will do them?) */
|
||||
close_socket(socket);
|
||||
close_socket(conn->data_socket);
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
socket->state = SOCKET_END_ONCLOSE;
|
||||
@ -477,7 +488,7 @@ smb_got_header(struct socket *socket, struct read_buffer *rb)
|
||||
|
||||
/* avoid error */
|
||||
if (!conn->est_length) {
|
||||
abort_connection(conn, S_OK);
|
||||
abort_connection(conn, connection_state(S_OK));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -492,14 +503,16 @@ smb_got_header(struct socket *socket, struct read_buffer *rb)
|
||||
if (!buf) {
|
||||
close_socket(socket);
|
||||
close_socket(conn->data_socket);
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
if (error) {
|
||||
mem_free_set(&conn->cached->content_type, stracpy("text/html"));
|
||||
read_from_socket(conn->data_socket, buf, S_CONN, smb_got_error);
|
||||
read_from_socket(conn->data_socket, buf,
|
||||
connection_state(S_CONN), smb_got_error);
|
||||
} else {
|
||||
read_from_socket(conn->data_socket, buf, S_CONN, smb_got_data);
|
||||
read_from_socket(conn->data_socket, buf,
|
||||
connection_state(S_CONN), smb_got_data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -535,7 +548,7 @@ smb_protocol_handler(struct connection *conn)
|
||||
if (smb_pipe[1] >= 0) close(smb_pipe[1]);
|
||||
if (header_pipe[0] >= 0) close(header_pipe[0]);
|
||||
if (header_pipe[1] >= 0) close(header_pipe[1]);
|
||||
abort_connection(conn, -s_errno);
|
||||
abort_connection(conn, connection_state_for_errno(s_errno));
|
||||
return;
|
||||
}
|
||||
conn->from = 0;
|
||||
@ -550,7 +563,7 @@ smb_protocol_handler(struct connection *conn)
|
||||
close(smb_pipe[1]);
|
||||
close(header_pipe[0]);
|
||||
close(header_pipe[1]);
|
||||
retry_connection(conn, -s_errno);
|
||||
retry_connection(conn, connection_state_for_errno(s_errno));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -594,9 +607,10 @@ smb_protocol_handler(struct connection *conn)
|
||||
if (!buf2) {
|
||||
close_socket(conn->data_socket);
|
||||
close_socket(conn->socket);
|
||||
abort_connection(conn, S_OUT_OF_MEM);
|
||||
abort_connection(conn, connection_state(S_OUT_OF_MEM));
|
||||
return;
|
||||
}
|
||||
read_from_socket(conn->socket, buf2, S_CONN, smb_got_header);
|
||||
read_from_socket(conn->socket, buf2,
|
||||
connection_state(S_CONN), smb_got_header);
|
||||
}
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ get_user_program(struct terminal *term, unsigned char *progid, int progidlen)
|
||||
|
||||
/* declared in "session/session.h" */
|
||||
void
|
||||
print_error_dialog(struct session *ses, enum connection_state state,
|
||||
print_error_dialog(struct session *ses, struct connection_state state,
|
||||
struct uri *uri, enum connection_priority priority)
|
||||
{
|
||||
stub_called("print_error_dialog");
|
||||
|
@ -68,7 +68,7 @@ int
|
||||
download_is_progressing(struct download *download)
|
||||
{
|
||||
return download
|
||||
&& download->state == S_TRANS
|
||||
&& is_in_state(download->state, S_TRANS)
|
||||
&& has_progress(download->progress);
|
||||
}
|
||||
|
||||
@ -318,9 +318,9 @@ download_data_store(struct download *download, struct file_download *file_downlo
|
||||
return;
|
||||
}
|
||||
|
||||
if (download->state != S_OK) {
|
||||
if (!is_in_state(download->state, S_OK)) {
|
||||
unsigned char *url = get_uri_string(file_download->uri, URI_PUBLIC);
|
||||
enum connection_state state = download->state;
|
||||
struct connection_state state = download->state;
|
||||
|
||||
abort_download_and_beep(file_download, term);
|
||||
|
||||
@ -398,7 +398,7 @@ download_data(struct download *download, struct file_download *file_download)
|
||||
done_uri(file_download->uri);
|
||||
|
||||
file_download->uri = get_uri_reference(cached->redirect);
|
||||
file_download->download.state = S_WAIT_REDIR;
|
||||
file_download->download.state = connection_state(S_WAIT_REDIR);
|
||||
|
||||
if (file_download->dlg_data)
|
||||
redraw_dialog(file_download->dlg_data, 1);
|
||||
@ -962,7 +962,7 @@ init_type_query(struct session *ses, struct download *download,
|
||||
object_lock(type_query->cached);
|
||||
|
||||
move_download(download, &type_query->download, PRI_MAIN);
|
||||
download->state = S_OK;
|
||||
download->state = connection_state(S_OK);
|
||||
|
||||
add_to_list(ses->type_queries, type_query);
|
||||
|
||||
|
@ -41,8 +41,8 @@ struct download {
|
||||
void *data;
|
||||
struct progress *progress;
|
||||
|
||||
enum connection_state state;
|
||||
enum connection_state prev_error;
|
||||
struct connection_state state;
|
||||
struct connection_state prev_error;
|
||||
enum connection_priority pri;
|
||||
};
|
||||
|
||||
|
@ -241,7 +241,7 @@ get_current_download(struct session *ses)
|
||||
else if (have_location(ses))
|
||||
download = &cur_loc(ses)->download;
|
||||
|
||||
if (download && download->state == S_OK) {
|
||||
if (download && is_in_state(download->state, S_OK)) {
|
||||
struct file_to_load *ftl;
|
||||
|
||||
foreach (ftl, ses->more_files)
|
||||
@ -255,7 +255,7 @@ get_current_download(struct session *ses)
|
||||
}
|
||||
|
||||
void
|
||||
print_error_dialog(struct session *ses, enum connection_state state,
|
||||
print_error_dialog(struct session *ses, struct connection_state state,
|
||||
struct uri *uri, enum connection_priority priority)
|
||||
{
|
||||
struct string msg;
|
||||
@ -602,7 +602,7 @@ doc_loading_callback(struct download *download, struct session *ses)
|
||||
|
||||
start_document_refreshes(ses);
|
||||
|
||||
if (download->state != S_OK) {
|
||||
if (!is_in_state(download->state, S_OK)) {
|
||||
print_error_dialog(ses, download->state,
|
||||
ses->doc_view->document->uri,
|
||||
download->pri);
|
||||
@ -838,7 +838,7 @@ setup_session(struct session *ses, struct uri *uri, struct session *base)
|
||||
struct location *loc = mem_calloc(1, sizeof(*loc));
|
||||
|
||||
if (loc) {
|
||||
loc->download.state = S_OK;
|
||||
loc->download.state = connection_state(S_OK);
|
||||
copy_location(loc, cur_loc(base));
|
||||
add_to_history(&ses->history, loc);
|
||||
render_document_frames(ses, 0);
|
||||
@ -1120,7 +1120,8 @@ decode_session_info(struct terminal *term, struct terminal_info *info)
|
||||
/* End loop if initialization fails */
|
||||
len = 0;
|
||||
} else if (bad_url) {
|
||||
print_error_dialog(ses, S_BAD_URL, NULL, PRI_MAIN);
|
||||
print_error_dialog(ses, connection_state(S_BAD_URL),
|
||||
NULL, PRI_MAIN);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -231,7 +231,7 @@ have_location(struct session *ses) {
|
||||
void set_session_referrer(struct session *ses, struct uri *referrer);
|
||||
|
||||
void
|
||||
print_error_dialog(struct session *ses, enum connection_state state,
|
||||
print_error_dialog(struct session *ses, struct connection_state state,
|
||||
struct uri *uri, enum connection_priority priority);
|
||||
|
||||
void process_file_requests(struct session *);
|
||||
|
@ -543,7 +543,8 @@ loading_callback(struct download *download, struct session *ses)
|
||||
if (d == DO_MOVE_DISPLAY) doc_loading_callback(download, ses);
|
||||
}
|
||||
|
||||
if (is_in_result_state(download->state) && download->state != S_OK) {
|
||||
if (is_in_result_state(download->state)
|
||||
&& !is_in_state(download->state, S_OK)) {
|
||||
print_error_dialog(ses, download->state,
|
||||
download->conn ? download->conn->uri : NULL,
|
||||
download->pri);
|
||||
@ -564,7 +565,7 @@ do_follow_url(struct session *ses, struct uri *uri, unsigned char *target,
|
||||
protocol_external_handler_T *external_handler;
|
||||
|
||||
if (!uri) {
|
||||
print_error_dialog(ses, S_BAD_URL, uri, PRI_CANCEL);
|
||||
print_error_dialog(ses, connection_state(S_BAD_URL), uri, PRI_CANCEL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
#define EL__VIEWER_ACTION_H
|
||||
|
||||
#include "config/kbdbind.h"
|
||||
#include "viewer/text/view.h"
|
||||
|
||||
struct session;
|
||||
|
||||
|
@ -263,7 +263,7 @@ dump_loading_callback(struct download *download, void *p)
|
||||
|
||||
}
|
||||
|
||||
if (download->state != S_OK) {
|
||||
if (!is_in_state(download->state, S_OK)) {
|
||||
usrerror(get_state_message(download->state, NULL));
|
||||
program.retval = RET_ERROR;
|
||||
goto terminate;
|
||||
|
@ -378,7 +378,13 @@ draw_formatted(struct session *ses, int rerender)
|
||||
void
|
||||
refresh_view(struct session *ses, struct document_view *doc_view, int frames)
|
||||
{
|
||||
draw_doc(ses, doc_view, 1);
|
||||
if (frames) draw_frames(ses);
|
||||
/* If refresh_view() is being called because the value of a
|
||||
* form field has changed, @ses might not be in the current
|
||||
* tab: consider SELECT pop-ups behind which -remote loads
|
||||
* another tab, or setTimeout in ECMAScript. */
|
||||
if (ses->tab == get_current_tab(ses->tab->term)) {
|
||||
draw_doc(ses, doc_view, 1);
|
||||
if (frames) draw_frames(ses);
|
||||
}
|
||||
print_screen_status(ses);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user