diff options
-rw-r--r-- | AUTHORS | 2 | ||||
-rw-r--r-- | ChangeLog | 2 | ||||
-rw-r--r-- | Doxyfile | 4 | ||||
-rw-r--r-- | configure.ac | 21 | ||||
-rw-r--r-- | devdoc/CCCwork.txt (renamed from doc/CCCwork.txt) | 0 | ||||
-rw-r--r-- | devdoc/Cache.txt (renamed from doc/Cache.txt) | 0 | ||||
-rw-r--r-- | devdoc/Dillo.txt (renamed from doc/Dillo.txt) | 0 | ||||
-rw-r--r-- | devdoc/Dpid.txt (renamed from doc/Dpid.txt) | 5 | ||||
-rw-r--r-- | devdoc/HtmlParser.txt (renamed from doc/HtmlParser.txt) | 0 | ||||
-rw-r--r-- | devdoc/IO.txt (renamed from doc/IO.txt) | 0 | ||||
-rw-r--r-- | devdoc/Images.txt (renamed from doc/Images.txt) | 3 | ||||
-rw-r--r-- | devdoc/NC_design.txt (renamed from doc/NC_design.txt) | 0 | ||||
-rw-r--r-- | devdoc/README | 51 | ||||
-rw-r--r-- | devdoc/dw-changes.doc (renamed from doc/dw-changes.doc) | 0 | ||||
-rw-r--r-- | devdoc/dw-example-screenshot.png (renamed from doc/dw-example-screenshot.png) | bin | 2264 -> 2264 bytes | |||
-rw-r--r-- | devdoc/dw-floats-01.png (renamed from doc/dw-floats-01.png) | bin | 3410 -> 3410 bytes | |||
-rw-r--r-- | devdoc/dw-grows.doc (renamed from doc/dw-grows.doc) | 0 | ||||
-rw-r--r-- | devdoc/dw-images-and-backgrounds.doc (renamed from doc/dw-images-and-backgrounds.doc) | 0 | ||||
-rw-r--r-- | devdoc/dw-layout-views.doc (renamed from doc/dw-layout-views.doc) | 0 | ||||
-rw-r--r-- | devdoc/dw-layout-widgets.doc (renamed from doc/dw-layout-widgets.doc) | 0 | ||||
-rw-r--r-- | devdoc/dw-line-breaking.doc (renamed from doc/dw-line-breaking.doc) | 0 | ||||
-rw-r--r-- | devdoc/dw-map.doc (renamed from doc/dw-map.doc) | 0 | ||||
-rw-r--r-- | devdoc/dw-out-of-flow-2.doc (renamed from doc/dw-out-of-flow-2.doc) | 0 | ||||
-rw-r--r-- | devdoc/dw-out-of-flow-floats.doc (renamed from doc/dw-out-of-flow-floats.doc) | 0 | ||||
-rw-r--r-- | devdoc/dw-out-of-flow.doc (renamed from doc/dw-out-of-flow.doc) | 0 | ||||
-rw-r--r-- | devdoc/dw-overview.doc (renamed from doc/dw-overview.doc) | 0 | ||||
-rw-r--r-- | devdoc/dw-size-of-widget.png (renamed from doc/dw-size-of-widget.png) | bin | 1749 -> 1749 bytes | |||
-rw-r--r-- | devdoc/dw-style-box-model.png (renamed from doc/dw-style-box-model.png) | bin | 3889 -> 3889 bytes | |||
-rw-r--r-- | devdoc/dw-style-length-absolute.png (renamed from doc/dw-style-length-absolute.png) | bin | 575 -> 575 bytes | |||
-rw-r--r-- | devdoc/dw-style-length-percentage.png (renamed from doc/dw-style-length-percentage.png) | bin | 890 -> 890 bytes | |||
-rw-r--r-- | devdoc/dw-style-length-relative.png (renamed from doc/dw-style-length-relative.png) | bin | 868 -> 868 bytes | |||
-rw-r--r-- | devdoc/dw-textblock-collapsing-spaces-1-1.png (renamed from doc/dw-textblock-collapsing-spaces-1-1.png) | bin | 641 -> 641 bytes | |||
-rw-r--r-- | devdoc/dw-textblock-collapsing-spaces-1-2.png (renamed from doc/dw-textblock-collapsing-spaces-1-2.png) | bin | 521 -> 521 bytes | |||
-rw-r--r-- | devdoc/dw-textblock-collapsing-spaces-2-1.png (renamed from doc/dw-textblock-collapsing-spaces-2-1.png) | bin | 802 -> 802 bytes | |||
-rw-r--r-- | devdoc/dw-textblock-collapsing-spaces-2-2.png (renamed from doc/dw-textblock-collapsing-spaces-2-2.png) | bin | 586 -> 586 bytes | |||
-rw-r--r-- | devdoc/dw-usage.doc (renamed from doc/dw-usage.doc) | 0 | ||||
-rw-r--r-- | devdoc/dw-viewport-with-scrollbar.png (renamed from doc/dw-viewport-with-scrollbar.png) | bin | 755 -> 755 bytes | |||
-rw-r--r-- | devdoc/dw-viewport-without-scrollbar.png (renamed from doc/dw-viewport-without-scrollbar.png) | bin | 542 -> 542 bytes | |||
-rw-r--r-- | devdoc/dw-widget-sizes.doc (renamed from doc/dw-widget-sizes.doc) | 0 | ||||
-rw-r--r-- | devdoc/fltk-problems.doc (renamed from doc/fltk-problems.doc) | 0 | ||||
-rw-r--r-- | devdoc/index.doc (renamed from doc/index.doc) | 0 | ||||
-rw-r--r-- | devdoc/lout.doc (renamed from doc/lout.doc) | 0 | ||||
-rw-r--r-- | devdoc/not-so-simple-container.png | bin | 0 -> 19319 bytes | |||
-rw-r--r-- | devdoc/not-so-simple-container.svg | 785 | ||||
-rw-r--r-- | devdoc/rounding-errors.doc (renamed from doc/rounding-errors.doc) | 0 | ||||
-rw-r--r-- | devdoc/uml-legend.doc (renamed from doc/uml-legend.doc) | 0 | ||||
-rw-r--r-- | dillorc | 2 | ||||
-rw-r--r-- | doc/Dw.txt | 11 | ||||
-rw-r--r-- | doc/Imgbuf.txt | 177 | ||||
-rw-r--r-- | doc/Makefile.am | 47 | ||||
-rw-r--r-- | doc/README | 54 | ||||
-rw-r--r-- | doc/Selection.txt | 149 | ||||
-rw-r--r-- | doc/dillo.1.in | 6 | ||||
-rw-r--r-- | doc/not-so-simple-container.png | bin | 5738 -> 0 bytes | |||
-rw-r--r-- | dpi/cookies.c | 22 | ||||
-rw-r--r-- | dpi/vsource.c | 70 | ||||
-rw-r--r-- | dpid/dpid_common.h | 1 | ||||
-rw-r--r-- | dpip/dpip.c | 21 | ||||
-rw-r--r-- | dpip/dpip.h | 1 | ||||
-rw-r--r-- | dw/table.cc | 20 | ||||
-rw-r--r-- | dw/table.hh | 32 | ||||
-rw-r--r-- | lout/msg.h | 1 | ||||
-rw-r--r-- | src/IO/IO.c | 10 | ||||
-rw-r--r-- | src/IO/Makefile.am | 4 | ||||
-rw-r--r-- | src/IO/http.c | 217 | ||||
-rw-r--r-- | src/IO/ssl.h | 47 | ||||
-rw-r--r-- | src/IO/tls.c (renamed from src/IO/ssl.c) | 431 | ||||
-rw-r--r-- | src/IO/tls.h | 47 | ||||
-rw-r--r-- | src/cache.c | 16 | ||||
-rw-r--r-- | src/dialog.cc | 20 | ||||
-rw-r--r-- | src/dillo.cc | 6 | ||||
-rw-r--r-- | src/html.cc | 2 | ||||
-rw-r--r-- | src/url.c | 25 | ||||
-rw-r--r-- | src/url.h | 10 |
74 files changed, 1434 insertions, 888 deletions
@@ -87,5 +87,5 @@ Non-Dillo code: * src/md5.[ch] contain code by L. Peter Deutsch whose copyright is held by Aladdin Enterprises. * src/tipwin.cc contains code by Greg Ercolano. -* src/IO/ssl.c contains code from wget whose copyright is held by the +* src/IO/tls.c contains code from wget whose copyright is held by the Free Software Foundation. @@ -34,6 +34,8 @@ dillo-3.1 [not released yet] Patches: Sebastian Geerken +- Image buffer/cache improvements. - Fix for segfault when there's no dpid and view source is requested. + - Fix view-source dpi to handle null characters correctly. + - Made view-source dpi use CSS formatting (it's shorter and cleaner). Patches: Jorge Arellano Cid +- Crosscompile/buildroot-friendly fltk-config test. Patch: Peter Seiderer @@ -852,7 +852,7 @@ EXAMPLE_RECURSIVE = NO # that contain images that are to be included in the documentation (see the # \image command). -IMAGE_PATH = doc +IMAGE_PATH = devdoc # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program @@ -1298,7 +1298,7 @@ QHP_NAMESPACE = # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. -QHP_VIRTUAL_FOLDER = doc +QHP_VIRTUAL_FOLDER = devdoc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom diff --git a/configure.ac b/configure.ac index db37619d..63f0f40e 100644 --- a/configure.ac +++ b/configure.ac @@ -24,10 +24,10 @@ AC_ARG_ENABLE(gprof, [ --enable-gprof Try to compile and run with pro , enable_gprof=no) AC_ARG_ENABLE(insure, [ --enable-insure Try to compile and run with Insure++], , enable_insure=no) -AC_ARG_ENABLE(ssl, [ --enable-ssl Enable ssl, https (ALPHA CODE)], +AC_ARG_ENABLE(ssl, [ --enable-ssl Enable SSL/HTTPS/TLS (EXPERIMENTAL CODE)], , enable_ssl=no) -AC_ARG_WITH(ca-certs-file, [ --with-ca-certs-file=FILE Specify where to find a bundle of trusted CA certificates for SSL], CA_CERTS_FILE=$withval) -AC_ARG_WITH(ca-certs-dir, [ --with-ca-certs-dir=DIR Specify where to find a directory containing trusted CA certificates for SSL], CA_CERTS_DIR=$withval) +AC_ARG_WITH(ca-certs-file, [ --with-ca-certs-file=FILE Specify where to find a bundle of trusted CA certificates for TLS], CA_CERTS_FILE=$withval) +AC_ARG_WITH(ca-certs-dir, [ --with-ca-certs-dir=DIR Specify where to find a directory containing trusted CA certificates for TLS], CA_CERTS_DIR=$withval) AC_ARG_ENABLE(ipv6, [ --enable-ipv6 Build with support for IPv6], , ) AC_ARG_ENABLE(cookies,[ --disable-cookies Don't compile support for cookies], , enable_cookies=yes) @@ -221,7 +221,10 @@ if test "x$enable_png" = "xyes"; then dnl Check if the user hasn't set the variable $PNG_CONFIG if test -z "$PNG_CONFIG"; then - PNG_CONFIG=`which libpng14-config` + PNG_CONFIG=`which libpng16-config` + if test -z "$PNG_CONFIG"; then + PNG_CONFIG=`which libpng14-config` + fi if test -z "$PNG_CONFIG"; then PNG_CONFIG=`which libpng12-config` fi @@ -247,7 +250,7 @@ dnl For debugging and to be user friendly AC_MSG_CHECKING([for libpng version]) png_version=`$PNG_CONFIG --version` case $png_version in - 1.[[024]].*) AC_MSG_RESULT([$png_version]) ;; + 1.[[0246]].*) AC_MSG_RESULT([$png_version]) ;; *) AC_MSG_RESULT([$png_version (unrecognised version)]) ;; esac @@ -287,7 +290,7 @@ if test "x$enable_gif" = "xyes"; then fi dnl -------------------------- -dnl Test for support for SSL +dnl Test for support for SSL/TLS dnl -------------------------- dnl if test "x$enable_ssl" = "xyes"; then @@ -301,14 +304,14 @@ if test "x$enable_ssl" = "xyes"; then if test "x$ssl_ok" = "xyes"; then LIBSSL_LIBS="-lcrypto -lssl" - AC_MSG_WARN([*** Enabling ssl support. THIS IS ALPHA CODE!***]) + AC_MSG_WARN([*** Enabling SSL/HTTPS/TLS support. THIS IS EXPERIMENTAL CODE ***]) else - AC_MSG_WARN([*** No libssl found. Disabling ssl support.***]) + AC_MSG_WARN([*** No libssl found. Disabling SSL/HTTPS/TLS support. ***]) fi fi if test "x$ssl_ok" = "xyes"; then - AC_DEFINE([ENABLE_SSL], [1], [Enable SSL support]) + AC_DEFINE([ENABLE_SSL], [1], [Enable SSL/HTTPS/TLS support]) fi dnl -------------------------------------------------------------- diff --git a/doc/CCCwork.txt b/devdoc/CCCwork.txt index 1ea5d20e..1ea5d20e 100644 --- a/doc/CCCwork.txt +++ b/devdoc/CCCwork.txt diff --git a/doc/Cache.txt b/devdoc/Cache.txt index 4e885df2..4e885df2 100644 --- a/doc/Cache.txt +++ b/devdoc/Cache.txt diff --git a/doc/Dillo.txt b/devdoc/Dillo.txt index a63c9588..a63c9588 100644 --- a/doc/Dillo.txt +++ b/devdoc/Dillo.txt diff --git a/doc/Dpid.txt b/devdoc/Dpid.txt index 82b81311..6c418f57 100644 --- a/doc/Dpid.txt +++ b/devdoc/Dpid.txt @@ -285,9 +285,10 @@ commented code in hello.c and start making changes! Debugging a dpi --------------- - The simplest way is to add printf() feedback using the MSG* + The simplest way is to add printf-like feedback using the MSG* macros. You can start the dpid by hand on a terminal to force -messages to go there. +messages to go there. Filter dpis use sdterr and server dpis +stdout. Sometimes more complex dpis need more than MSG*. In this case you can use gdb like this. diff --git a/doc/HtmlParser.txt b/devdoc/HtmlParser.txt index 2eb8be63..2eb8be63 100644 --- a/doc/HtmlParser.txt +++ b/devdoc/HtmlParser.txt diff --git a/doc/IO.txt b/devdoc/IO.txt index cd62a4f5..cd62a4f5 100644 --- a/doc/IO.txt +++ b/devdoc/IO.txt diff --git a/doc/Images.txt b/devdoc/Images.txt index 6a36e6f5..62082e48 100644 --- a/doc/Images.txt +++ b/devdoc/Images.txt @@ -1,5 +1,8 @@ January 2009, --Jcid +Update June 2015: See also doc/dw-images-and-backgrounds.doc, or +../html/dw-images-and-backgrounds.html (generated by doxygen). + ------ IMAGES ------ diff --git a/doc/NC_design.txt b/devdoc/NC_design.txt index 380787f6..380787f6 100644 --- a/doc/NC_design.txt +++ b/devdoc/NC_design.txt diff --git a/devdoc/README b/devdoc/README new file mode 100644 index 00000000..9736a32b --- /dev/null +++ b/devdoc/README @@ -0,0 +1,51 @@ +README: Last update Jul 2009 + +These documents cover dillo's internals. +For user help, see http://www.dillo.org/dillo3-help.html + +-------------------------------------------------------------------------- + +These documents need a review. +*.txt were current with Dillo1, but many have since become more or + less out-of-date. +*.doc are doxygen source for the Dillo Widget (dw) component, and + were written for Dillo2. + +They will give you an overview of what's going on, but take them +with a pinch of salt. + + Of course I'd like to have *.txt as doxygen files too! +If somebody wants to make this conversion, please let me know +to assign higher priority to updating these docs. + +-- +Jorge.- + + -------------------------------------------------------------------------- + FILE DESCRIPTION STATE + -------------------------------------------------------------------------- + NC_design.txt Naming&Coding design (Be sure to Current + read it before any other doc) + Dillo.txt General overview of the program Current + IO.txt Extensive introduction Current + Cache.txt Informative description Current + Images.txt Image handling and processing Current + HtmlParser.txt A versatile parser Current + Dw.txt The New Dillo Widget (Overview) Current + Imgbuf.txt Image buffers Pending + Selection.txt Selections, and link activation Current (?) + Cookies.txt Explains how to enable cookies Current + Dpid.txt Dillo plugin daemon Current + -------------------------------------------------------------------------- + + + * BTW, there's a small program (srch) within the src/ dir. It searches + tokens within the whole code (*.[ch]). It has proven very useful. + Ex: ./srch a_Image_write + ./srch todo: + + * Please submit your patches with 'hg diff'. + + + Happy coding! + --Jcid diff --git a/doc/dw-changes.doc b/devdoc/dw-changes.doc index 7050df9a..7050df9a 100644 --- a/doc/dw-changes.doc +++ b/devdoc/dw-changes.doc diff --git a/doc/dw-example-screenshot.png b/devdoc/dw-example-screenshot.png Binary files differindex 94f272ab..94f272ab 100644 --- a/doc/dw-example-screenshot.png +++ b/devdoc/dw-example-screenshot.png diff --git a/doc/dw-floats-01.png b/devdoc/dw-floats-01.png Binary files differindex 116d36b3..116d36b3 100644 --- a/doc/dw-floats-01.png +++ b/devdoc/dw-floats-01.png diff --git a/doc/dw-grows.doc b/devdoc/dw-grows.doc index c255419f..c255419f 100644 --- a/doc/dw-grows.doc +++ b/devdoc/dw-grows.doc diff --git a/doc/dw-images-and-backgrounds.doc b/devdoc/dw-images-and-backgrounds.doc index 8f07766a..8f07766a 100644 --- a/doc/dw-images-and-backgrounds.doc +++ b/devdoc/dw-images-and-backgrounds.doc diff --git a/doc/dw-layout-views.doc b/devdoc/dw-layout-views.doc index d1118489..d1118489 100644 --- a/doc/dw-layout-views.doc +++ b/devdoc/dw-layout-views.doc diff --git a/doc/dw-layout-widgets.doc b/devdoc/dw-layout-widgets.doc index e0215562..e0215562 100644 --- a/doc/dw-layout-widgets.doc +++ b/devdoc/dw-layout-widgets.doc diff --git a/doc/dw-line-breaking.doc b/devdoc/dw-line-breaking.doc index 14ab97c4..14ab97c4 100644 --- a/doc/dw-line-breaking.doc +++ b/devdoc/dw-line-breaking.doc diff --git a/doc/dw-map.doc b/devdoc/dw-map.doc index aebeb7da..aebeb7da 100644 --- a/doc/dw-map.doc +++ b/devdoc/dw-map.doc diff --git a/doc/dw-out-of-flow-2.doc b/devdoc/dw-out-of-flow-2.doc index d9d70565..d9d70565 100644 --- a/doc/dw-out-of-flow-2.doc +++ b/devdoc/dw-out-of-flow-2.doc diff --git a/doc/dw-out-of-flow-floats.doc b/devdoc/dw-out-of-flow-floats.doc index 53c6b220..53c6b220 100644 --- a/doc/dw-out-of-flow-floats.doc +++ b/devdoc/dw-out-of-flow-floats.doc diff --git a/doc/dw-out-of-flow.doc b/devdoc/dw-out-of-flow.doc index eda6994a..eda6994a 100644 --- a/doc/dw-out-of-flow.doc +++ b/devdoc/dw-out-of-flow.doc diff --git a/doc/dw-overview.doc b/devdoc/dw-overview.doc index 0c4ffb53..0c4ffb53 100644 --- a/doc/dw-overview.doc +++ b/devdoc/dw-overview.doc diff --git a/doc/dw-size-of-widget.png b/devdoc/dw-size-of-widget.png Binary files differindex dbdbe0c4..dbdbe0c4 100644 --- a/doc/dw-size-of-widget.png +++ b/devdoc/dw-size-of-widget.png diff --git a/doc/dw-style-box-model.png b/devdoc/dw-style-box-model.png Binary files differindex bf2fb1f1..bf2fb1f1 100644 --- a/doc/dw-style-box-model.png +++ b/devdoc/dw-style-box-model.png diff --git a/doc/dw-style-length-absolute.png b/devdoc/dw-style-length-absolute.png Binary files differindex 9ea28cad..9ea28cad 100644 --- a/doc/dw-style-length-absolute.png +++ b/devdoc/dw-style-length-absolute.png diff --git a/doc/dw-style-length-percentage.png b/devdoc/dw-style-length-percentage.png Binary files differindex b1ad79c9..b1ad79c9 100644 --- a/doc/dw-style-length-percentage.png +++ b/devdoc/dw-style-length-percentage.png diff --git a/doc/dw-style-length-relative.png b/devdoc/dw-style-length-relative.png Binary files differindex ee79b1a9..ee79b1a9 100644 --- a/doc/dw-style-length-relative.png +++ b/devdoc/dw-style-length-relative.png diff --git a/doc/dw-textblock-collapsing-spaces-1-1.png b/devdoc/dw-textblock-collapsing-spaces-1-1.png Binary files differindex d528dfb2..d528dfb2 100644 --- a/doc/dw-textblock-collapsing-spaces-1-1.png +++ b/devdoc/dw-textblock-collapsing-spaces-1-1.png diff --git a/doc/dw-textblock-collapsing-spaces-1-2.png b/devdoc/dw-textblock-collapsing-spaces-1-2.png Binary files differindex 483e79d1..483e79d1 100644 --- a/doc/dw-textblock-collapsing-spaces-1-2.png +++ b/devdoc/dw-textblock-collapsing-spaces-1-2.png diff --git a/doc/dw-textblock-collapsing-spaces-2-1.png b/devdoc/dw-textblock-collapsing-spaces-2-1.png Binary files differindex 0a03ea80..0a03ea80 100644 --- a/doc/dw-textblock-collapsing-spaces-2-1.png +++ b/devdoc/dw-textblock-collapsing-spaces-2-1.png diff --git a/doc/dw-textblock-collapsing-spaces-2-2.png b/devdoc/dw-textblock-collapsing-spaces-2-2.png Binary files differindex b89c6254..b89c6254 100644 --- a/doc/dw-textblock-collapsing-spaces-2-2.png +++ b/devdoc/dw-textblock-collapsing-spaces-2-2.png diff --git a/doc/dw-usage.doc b/devdoc/dw-usage.doc index a23920b8..a23920b8 100644 --- a/doc/dw-usage.doc +++ b/devdoc/dw-usage.doc diff --git a/doc/dw-viewport-with-scrollbar.png b/devdoc/dw-viewport-with-scrollbar.png Binary files differindex 7ac62de3..7ac62de3 100644 --- a/doc/dw-viewport-with-scrollbar.png +++ b/devdoc/dw-viewport-with-scrollbar.png diff --git a/doc/dw-viewport-without-scrollbar.png b/devdoc/dw-viewport-without-scrollbar.png Binary files differindex 8aa20fec..8aa20fec 100644 --- a/doc/dw-viewport-without-scrollbar.png +++ b/devdoc/dw-viewport-without-scrollbar.png diff --git a/doc/dw-widget-sizes.doc b/devdoc/dw-widget-sizes.doc index ffc7fb5d..ffc7fb5d 100644 --- a/doc/dw-widget-sizes.doc +++ b/devdoc/dw-widget-sizes.doc diff --git a/doc/fltk-problems.doc b/devdoc/fltk-problems.doc index df4f1f14..df4f1f14 100644 --- a/doc/fltk-problems.doc +++ b/devdoc/fltk-problems.doc diff --git a/doc/index.doc b/devdoc/index.doc index 59de8cd8..59de8cd8 100644 --- a/doc/index.doc +++ b/devdoc/index.doc diff --git a/doc/lout.doc b/devdoc/lout.doc index 4e1503c6..4e1503c6 100644 --- a/doc/lout.doc +++ b/devdoc/lout.doc diff --git a/devdoc/not-so-simple-container.png b/devdoc/not-so-simple-container.png Binary files differnew file mode 100644 index 00000000..f3e2c039 --- /dev/null +++ b/devdoc/not-so-simple-container.png diff --git a/devdoc/not-so-simple-container.svg b/devdoc/not-so-simple-container.svg new file mode 100644 index 00000000..ce00510e --- /dev/null +++ b/devdoc/not-so-simple-container.svg @@ -0,0 +1,785 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="210mm" + height="297mm" + id="svg2" + version="1.1" + inkscape:version="0.48.3.1 r9886" + sodipodi:docname="not-so-simple-container.svg" + inkscape:export-filename="/home/sg/dev/dillo/dillo/doc/not-so-simple-container.png" + inkscape:export-xdpi="69" + inkscape:export-ydpi="69"> + <defs + id="defs4"> + <marker + inkscape:stockid="Arrow1Mend" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow1Mend" + style="overflow:visible;"> + <path + id="path3998" + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;" + transform="scale(0.4) rotate(180) translate(10,0)" /> + </marker> + <marker + inkscape:stockid="Arrow1Send" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow1Send" + style="overflow:visible;"> + <path + id="path4004" + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;" + transform="scale(0.2) rotate(180) translate(6,0)" /> + </marker> + <marker + inkscape:stockid="Arrow1Lend" + orient="auto" + refY="0.0" + refX="0.0" + id="Arrow1Lend" + style="overflow:visible;"> + <path + id="path3992" + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;" + transform="scale(0.8) rotate(180) translate(12.5,0)" /> + </marker> + <marker + inkscape:stockid="Arrow1Mend" + orient="auto" + refY="0" + refX="0" + id="Arrow1Mend-5" + style="overflow:visible"> + <path + inkscape:connector-curvature="0" + id="path3998-5" + d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" + transform="matrix(-0.4,0,0,-0.4,-4,0)" /> + </marker> + <marker + inkscape:stockid="Arrow1Mend" + orient="auto" + refY="0" + refX="0" + id="Arrow1Mend-3" + style="overflow:visible"> + <path + inkscape:connector-curvature="0" + id="path3998-2" + d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" + transform="matrix(-0.4,0,0,-0.4,-4,0)" /> + </marker> + <marker + inkscape:stockid="Arrow1Mend" + orient="auto" + refY="0" + refX="0" + id="Arrow1Mend-2" + style="overflow:visible"> + <path + inkscape:connector-curvature="0" + id="path3998-22" + d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" + transform="matrix(-0.4,0,0,-0.4,-4,0)" /> + </marker> + <marker + inkscape:stockid="Arrow1Mend" + orient="auto" + refY="0" + refX="0" + id="marker4917" + style="overflow:visible"> + <path + inkscape:connector-curvature="0" + id="path4919" + d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" + transform="matrix(-0.4,0,0,-0.4,-4,0)" /> + </marker> + <marker + inkscape:stockid="Arrow1Mend" + orient="auto" + refY="0" + refX="0" + id="marker4921" + style="overflow:visible"> + <path + inkscape:connector-curvature="0" + id="path4923" + d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" + transform="matrix(-0.4,0,0,-0.4,-4,0)" /> + </marker> + <marker + inkscape:stockid="Arrow1Mend" + orient="auto" + refY="0" + refX="0" + id="Arrow1Mend-9" + style="overflow:visible"> + <path + inkscape:connector-curvature="0" + id="path3998-7" + d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" + transform="matrix(-0.4,0,0,-0.4,-4,0)" /> + </marker> + <marker + inkscape:stockid="Arrow1Mend" + orient="auto" + refY="0" + refX="0" + id="Arrow1Mend-6" + style="overflow:visible"> + <path + inkscape:connector-curvature="0" + id="path3998-6" + d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" + transform="matrix(-0.4,0,0,-0.4,-4,0)" /> + </marker> + <marker + inkscape:stockid="Arrow1Mend" + orient="auto" + refY="0" + refX="0" + id="Arrow1Mend-51" + style="overflow:visible"> + <path + inkscape:connector-curvature="0" + id="path3998-3" + d="M 0,0 5,-5 -12.5,0 5,5 0,0 z" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt" + transform="matrix(-0.4,0,0,-0.4,-4,0)" /> + </marker> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1" + inkscape:cx="226.09436" + inkscape:cy="741.31258" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:window-width="1598" + inkscape:window-height="876" + inkscape:window-x="0" + inkscape:window-y="22" + inkscape:window-maximized="1"> + <inkscape:grid + type="xygrid" + id="grid2985" /> + </sodipodi:namedview> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Ebene 1" + inkscape:groupmode="layer" + id="layer1"> + <rect + style="fill:#e0e0e0;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3010" + width="35.433071" + height="17.716536" + x="442.91339" + y="25.611128" /> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Nimbus Mono L;-inkscape-font-specification:Nimbus Mono L" + x="496.06299" + y="38.581394" + id="text3012" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan3014" + x="496.06299" + y="38.581394" + style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L">unaffected (in main array)</tspan></text> + <flowRoot + xml:space="preserve" + id="flowRoot3800" + style="fill:black;stroke:none;stroke-opacity:1;stroke-width:1px;stroke-linejoin:miter;stroke-linecap:butt;fill-opacity:1;font-family:Nimbus Mono L;font-style:normal;font-weight:normal;font-size:20px;line-height:125%;letter-spacing:0px;word-spacing:0px;-inkscape-font-specification:Nimbus Mono L;font-stretch:normal;font-variant:normal"><flowRegion + id="flowRegion3802"><rect + id="rect3804" + width="276.7818" + height="34.345188" + x="424.26407" + y="20.996433" /></flowRegion><flowPara + id="flowPara3806" /></flowRoot> <rect + style="fill:#e0e0e0;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3812" + width="70.866142" + height="17.716536" + x="17.716558" + y="60.236198" /> + <rect + style="fill:#b0b0ff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3814" + width="35.433071" + height="17.716536" + x="442.91339" + y="61.480198" /> + <rect + style="fill:#80ff00;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3816" + width="35.433071" + height="17.716536" + x="442.91339" + y="96.913269" /> + <rect + style="fill:#ffff40;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3818" + width="35.433071" + height="17.716536" + x="442.91339" + y="131.10234" /> + <rect + style="fill:#b0b0ff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3816-2" + width="88.58268" + height="17.716536" + x="124.01577" + y="60.236198" /> + <rect + style="fill:#e0e0e0;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3812-5" + width="88.582687" + height="17.716536" + x="301.18112" + y="60.236198" /> + <rect + style="fill:#80ff00;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3816-4" + width="35.433071" + height="17.716536" + x="442.91339" + y="96.913269" /> + <rect + style="fill:#80ff00;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3816-4-2" + width="35.433071" + height="17.716536" + x="88.582703" + y="95.669266" /> + <path + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + d="m 17.716558,60.236198 70.866142,0 0,17.716536 -70.866142,0" + id="path3939" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + d="m 389.7638,60.236198 -88.58268,0 0,17.716536 88.58268,0" + id="path3941" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + <rect + style="fill:#e0e0e0;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3812-3" + width="70.866142" + height="17.716536" + x="17.71656" + y="148.81888" /> + <rect + style="fill:#e0e0e0;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3812-5-7" + width="88.582687" + height="17.716537" + x="301.18112" + y="148.81888" /> + <path + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + d="m 17.716558,148.81888 70.86614,0 0,17.71653 -70.86614,0" + id="path3939-4" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + d="m 389.7638,148.81887 -88.58268,1e-5 0,17.71653 88.58268,0" + id="path3941-8" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + <rect + style="fill:#80ff00;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3816-4-2-6" + width="35.433071" + height="17.716536" + x="124.01577" + y="148.81888" /> + <rect + style="fill:#b0b0ff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3816-2-5" + width="53.149605" + height="17.716537" + x="159.44885" + y="148.81888" /> + <rect + style="fill:#b0b0ff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3816-2-50" + width="35.433067" + height="17.716537" + x="212.59845" + y="184.25195" /> + <rect + style="fill:#ffff40;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3818-4" + width="53.149609" + height="17.716534" + x="248.03152" + y="184.25195" /> + <path + style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 88.5827,148.81887 35.43307,0" + id="path4078-6" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 88.5827,166.53541 35.43307,0" + id="path4078-4-7" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 212.59845,60.236198 88.58267,0" + id="path4078-66" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 212.59845,77.952734 88.58267,0" + id="path4078-4-0" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#8080ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:2, 4;stroke-dashoffset:0" + d="m 88.5827,77.952734 0,17.716535" + id="path4156" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:#808000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 88.5827,77.952734 0,17.716535" + id="path4176" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:#808000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 124.01577,95.669269 0,-17.716535" + id="path4178" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:#808000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 212.59845,166.53541 0,17.71654" + id="path4180" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:#808000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 301.18112,184.25195 0,-17.71654" + id="path4182" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:#8080ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 88.5827,77.952734 0,17.716535" + id="path4186" + inkscape:connector-curvature="0" + inkscape:export-filename="/home/sg/dev/dillo/dillo/doc/path4188.png" + inkscape:export-xdpi="69" + inkscape:export-ydpi="69" /> + <path + style="fill:none;stroke:#8080ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 124.01577,95.669269 0,-17.716535" + id="path4188" + inkscape:connector-curvature="0" + inkscape:export-xdpi="69" + inkscape:export-ydpi="69" /> + <path + style="fill:none;stroke:#8080ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 212.59845,166.53541 0,17.71654" + id="path4190" + inkscape:connector-curvature="0" + inkscape:export-filename="/home/sg/dev/dillo/dillo/doc/path4188.png" + inkscape:export-xdpi="69" + inkscape:export-ydpi="69" /> + <path + style="fill:none;stroke:#8080ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 301.18112,184.25195 0,-17.71654" + id="path4192" + inkscape:connector-curvature="0" + inkscape:export-filename="/home/sg/dev/dillo/dillo/doc/path4188.png" + inkscape:export-xdpi="69" + inkscape:export-ydpi="69" /> + <path + style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 88.5827,77.952734 0,17.716535" + id="path4078-6-0" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 124.01577,77.952734 0,17.716535" + id="path4078-6-0-9" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 212.59845,166.53541 0,17.71654" + id="path4078-6-0-0" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 301.18112,166.53541 0,17.71654" + id="path4078-6-0-6" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-end:url(#Arrow1Mend)" + d="m 106.29923,116.92911 c 35.43307,28.34646 0,0 35.43307,28.34646" + id="path3803" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-end:url(#Arrow1Mend)" + d="m 148.81892,81.496041 c 35.43307,63.779529 0,0 35.43307,63.779529" + id="path3803-7" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 177.16537,60.236198 0,17.716535" + id="path4078-6-0-9-5" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-end:url(#Arrow1Mend)" + d="m 194.88191,81.496038 c 35.43307,99.212602 0,3e-6 35.43307,99.212602" + id="path3803-7-0" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Nimbus Mono L;-inkscape-font-specification:Nimbus Mono L" + x="496.06299" + y="74.426468" + id="text3012-5" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan3014-0" + x="496.06299" + y="74.426468" + style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L">main array (moved)</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L" + x="496.06299" + y="109.85954" + id="text4897" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4899" + x="496.06299" + y="109.85954" + style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L">original extra array</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Nimbus Mono L;-inkscape-font-specification:Nimbus Mono L" + x="496.06299" + y="145.60861" + id="text4901" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan4903" + x="496.06299" + y="145.60861" + style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L">new inserted area</tspan></text> + <rect + style="fill:#e0e0e0;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3812-37" + width="53.149609" + height="17.716536" + x="17.716558" + y="272.83463" /> + <rect + style="fill:#b0b0ff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3816-2-1" + width="35.433067" + height="17.716537" + x="159.44884" + y="272.83463" /> + <rect + style="fill:#e0e0e0;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3812-5-5" + width="53.149582" + height="17.716537" + x="336.61423" + y="272.83463" /> + <rect + style="fill:#80ff00;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3816-4-2-3" + width="88.582664" + height="17.716534" + x="70.866173" + y="308.2677" /> + <path + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + d="m 17.716558,272.83462 53.149615,0 0,17.71654 -53.149615,0" + id="path3939-43" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + <path + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + d="m 389.7638,272.83462 -53.14961,0 0,17.71654 53.14961,0" + id="path3941-6" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + <rect + style="fill:#e0e0e0;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3812-3-3" + width="53.149624" + height="17.716515" + x="17.716558" + y="361.4173" /> + <rect + style="fill:#e0e0e0;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3812-5-7-9" + width="53.149582" + height="17.716543" + x="336.61423" + y="361.4173" /> + <path + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + d="m 17.716559,361.4173 53.149604,0 0,17.71653 -53.149604,1e-5" + id="path3939-4-2" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + <path + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + d="m 389.7638,361.4173 -53.14961,0 0,17.71653 53.14961,1e-5" + id="path3941-8-1" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + <rect + style="fill:#80ff00;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3816-4-2-6-7" + width="35.433071" + height="17.716536" + x="159.44884" + y="361.4173" /> + <rect + style="fill:#b0b0ff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3816-2-50-6" + width="35.433067" + height="17.716537" + x="248.03151" + y="396.85037" /> + <rect + style="fill:#ffff40;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3818-4-9" + width="53.149609" + height="17.716534" + x="283.4646" + y="396.85037" /> + <path + style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 70.866173,361.41729 88.582667,1e-5" + id="path4078-6-8" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 70.866173,379.13383 88.582667,1e-5" + id="path4078-4-7-4" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 194.88192,272.83462 141.73227,0" + id="path4078-66-9" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 194.88192,290.55116 141.73227,0" + id="path4078-4-0-6" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#8080ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:2, 4;stroke-dashoffset:0" + d="m 70.866173,290.55116 0,17.71653" + id="path4156-9" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#808000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 70.866173,290.55116 0,17.71653" + id="path4176-4" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#808000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 106.29924,308.26769 0,-17.71653" + id="path4178-9" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:#808000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 194.88192,379.13383 0,17.71654" + id="path4180-3" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:#808000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 336.61419,396.85037 0,-17.71654" + id="path4182-8" + inkscape:connector-curvature="0" /> + <path + style="fill:none;stroke:#8080ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 70.866173,290.55116 0,17.71653" + id="path4186-1" + inkscape:connector-curvature="0" + inkscape:export-filename="/home/sg/dev/dillo/dillo/doc/path4188.png" + inkscape:export-xdpi="69" + inkscape:export-ydpi="69" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#8080ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 106.29924,308.26769 0,-17.71653" + id="path4188-2" + inkscape:connector-curvature="0" + inkscape:export-xdpi="69" + inkscape:export-ydpi="69" /> + <path + style="fill:none;stroke:#8080ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 194.88192,379.13383 0,17.71654" + id="path4190-8" + inkscape:connector-curvature="0" + inkscape:export-filename="/home/sg/dev/dillo/dillo/doc/path4188.png" + inkscape:export-xdpi="69" + inkscape:export-ydpi="69" /> + <path + style="fill:none;stroke:#8080ff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 336.61419,396.85037 0,-17.71654" + id="path4192-4" + inkscape:connector-curvature="0" + inkscape:export-filename="/home/sg/dev/dillo/dillo/doc/path4188.png" + inkscape:export-xdpi="69" + inkscape:export-ydpi="69" /> + <path + style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 70.866173,290.55116 0,17.71653" + id="path4078-6-0-4" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 159.44883,290.55116 0,17.71653" + id="path4078-6-0-9-0" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 194.88192,379.13383 0,17.71654" + id="path4078-6-0-0-7" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#808080;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 336.61419,379.13383 0,17.71654" + id="path4078-6-0-6-1" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <rect + style="fill:#80ff00;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" + id="rect3816-4-2-6-7-8" + width="53.149616" + height="17.716539" + x="194.88191" + y="396.85037" /> + <path + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:4, 2;stroke-dashoffset:0" + d="m 106.29924,308.26769 0,17.71654" + id="path4078-6-0-9-5-1" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-end:url(#Arrow1Mend)" + d="m 88.5827,329.52754 c 88.58267,28.34645 0,0 88.58267,28.34645" + id="path3803-4" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-end:url(#Arrow1Mend)" + d="m 131.10238,329.52754 c 70.86614,24.80315 53.14961,3.5433 88.58268,63.77952" + id="path3803-4-0" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none;marker-end:url(#Arrow1Mend)" + d="m 177.16537,294.09447 c 88.58268,99.21259 0,0 88.58268,99.21259" + id="path3803-4-01" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Nimbus Mono L;-inkscape-font-specification:Nimbus Mono L" + x="17.716536" + y="42.519665" + id="text3012-5-7" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan3014-0-2" + x="17.716536" + y="42.519665" + style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L">Example 1:</tspan></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Nimbus Mono L;-inkscape-font-specification:Nimbus Mono L" + x="528" + y="389.36218" + id="text5205" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan5207" + x="528" + y="389.36218" /></text> + <text + xml:space="preserve" + style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Nimbus Mono L;-inkscape-font-specification:Nimbus Mono L" + x="17.716536" + y="255.11809" + id="text3012-5-7-9" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + x="17.716536" + y="255.11809" + style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L" + id="tspan5230">Example 2:</tspan></text> + </g> +</svg> diff --git a/doc/rounding-errors.doc b/devdoc/rounding-errors.doc index a442033e..a442033e 100644 --- a/doc/rounding-errors.doc +++ b/devdoc/rounding-errors.doc diff --git a/doc/uml-legend.doc b/devdoc/uml-legend.doc index 54004ccd..54004ccd 100644 --- a/doc/uml-legend.doc +++ b/devdoc/uml-legend.doc @@ -189,7 +189,7 @@ search_url="Google http://www.google.com/search?ie=UTF-8&oe=UTF-8&q=%s" # page/image/stylesheet. #http_persistent_conns=NO -# Set the proxy information for http. +# Set the proxy information for http/https. # Note that the http_proxy environment variable overrides this setting. # WARNING: FTP and downloads plugins use wget. To use a proxy with them, # you will need to configure wget accordingly. See diff --git a/doc/Dw.txt b/doc/Dw.txt deleted file mode 100644 index f6909380..00000000 --- a/doc/Dw.txt +++ /dev/null @@ -1,11 +0,0 @@ -Last update: Oct 2008 - -================ -Dw: Dillo Widget -================ - -Dw is the internal widget library for rendering HTML. It has excellent -documentation. - - Just run "doxygen" and browse the html/ directory! - diff --git a/doc/Imgbuf.txt b/doc/Imgbuf.txt deleted file mode 100644 index f4a56660..00000000 --- a/doc/Imgbuf.txt +++ /dev/null @@ -1,177 +0,0 @@ -Aug 2004, S.Geerken@ping.de - -============= -Image Buffers -============= - -General -======= - -Image buffers depend on the platform (see DwRender.txt), but have a -general, platform independant interface, which is described in this -section. The next section describes the Gdk version of Imgbuf. - -The structure ImgBuf will become part of the image processing, between -image data decoding and the widget DwImage. Its purposes are - - 1. storing the image data, - 2. handling scaled versions of this buffer, and - 3. drawing. - -The latter must be done independently from the window. - -Storing Image Data ------------------- -Imgbuf supports five image types, which are listed in the table -below. The representation defines, how the colors are stored within -the data, which is passed to a_Imgbuf_copy_row(). - - | bytes per | - type | pixel | representation - ---------------+-----------+------------------------- - RGB | 3 | red, green, blue - RGBA | 4 | red, green, blue, alpha - gray | 1 | gray value - indexed | 1 | index to colormap - indexed alpha | 1 | index to colormap - -The last two types need a colormap, which is set by -a_Imgbuf_set_cmap(), which must be called before -a_Imgbuf_copy_row(). This function expects the colors as 32 bit -unsigned integers, which have the format 0xrrbbgg (for indexed -images), or 0xaarrggbb (for indexed alpha), respectively. - -Scaling -------- -The buffer with the original size, which was created by -a_Imgbuf_new(), is called root buffer. Imgbuf provides the ability to -scale buffers. Generally, both root buffers, as well as scaled -buffers, may be shared, memory management is done by reference -counters. - -Via a_Imgbuf_get_scaled_buf(), you can retrieve a scaled buffer. The -way, how this function works in detail, is described in the code, but -generally, something like this works always, in an efficient way: - - old_buf = cur_buf; - cur_buf = a_Imgbuf_get_scaled_buf(old_buf, with, height); - a_Imgbuf_unref (old_buf); - -Old_buf may both be a root buffer, or a scaled buffer. - -(As an exception, there should always be a reference on the root -buffer, since scaled buffers cannot exist without the root buffer, but -on the other side, do not hold references on it. So, if in the example -above, old_buf would be a root buffer, and there would, at the -beginning, only be one reference on it, new_buf would also be -destroyed, along with old_buf. Therefore, an external reference must -be added to the root buffer, which is in dillo done within the dicache -module.) - -The root buffer keeps a list of all children, and all operations -operating on the image data (a_Imgbuf_copy_row() and -a_Imgbuf_set_cmap()) are delegated to the scaled buffers, when -processed, and inherited, when a new scaled buffer is created. This -means, that they must only be performed for the root buffer. - -Drawing -------- -There are two situations, when drawing is necessary: - - 1. To react on expose events, the function a_Imgbuf_draw() can be - used. Notice that the exact signature of this function is - platform dependant. - - 2. When a row has been copied, it has to be drawn. To determine the - area, which has to be drawn, the function - a_Imgbuf_get_row_area() should be used. In dillo, the dicache - module will first call a_Img_copy_row(), and then call - a_Dw_image_draw_row() for the images connected to this image - buffer. a_Dw_image_draw_row() will then call - p_Dw_widget_queue_draw(), with an area determined by - a_Imgbuf_get_row_area(). - - -The Gdk Implementation -====================== - -The Gdk implementation is used by the Gtk+ platform. [... todo] - - -Global Scalers -============== - -In some cases, there is a context, where images have to be scaled -often, by a relatively constant factor. For example, the preview -window (GtkDwPreview) draws images via the Imgbuf draw functions, but -uses scaled buffers. Scaling such a buffer each time it is needed, -causes huge performance losses. On the other hand, if the preview -window would keep these scaled buffers (e.g. by lazy mapping of the -original buffer to the scaled buffer), the scaled buffers get never -freed, since the view is not told about, when the original buffer is -not needed anymore. (n.b., that currently, the scaled buffers are -destroyed, when the original buffer is destroyed, but this may change, -and even this would leave "zombies" in this mapping structure, where -the values refer to dead pointers). - -It is sufficient, that references on the scaled buffers are referred -somehow, so that they do not get destroyed between different -usages. The caller (in this case the preview) simply requests a scaled -buffer, but the Imgbuf returns this from the list of already scaled -buffers. - -These references are hold by special structures, which are called -"scalers". There are two types of scalers, local scalers, which are -bound to image buffers, and global scalers, which refer to multiple -scalers. - -What happens in different situations: - - - The caller (e.g. the preview) requests a scaled buffer. For this, - it uses a special method, which also passes the global image - scaler, which was created before (for the preview, there is a 1-1 - association). The Imgbuf uses this global image scaler, to - identify the caller, and keeps a list of them. If this global - scaler is not yet in the list, it is added, and a local scaler is - created. - - - - - - -There are three images in the page, i1a, i1b, and i2. I1a and i1b -refer to the same image recource, represented by the root image buffer -iba, which original size is 200 x 200. I1a is displayed in original -size, while i1b is displayed at 100 x 100. I2 refers to an other -recource, ibb, which has the size 300 x 300. I2 is shown in original -size. - - - :DwRenderLayout ------------------- :DwPage ----------. - / \ | - ,----' `----. ,------ i1a:DwImage --+ - / \ | | - view1:GtkDwViewport view2:GtkDwPreview | ,---- i1b:DwImage --| - | | | | - ,------------------------------' | | ,-- i2: DwImage --' - | | | | - | ,-------------------------------------' | | - | | ,--------------------------------' | - | | | ,----' - | | | | - | V | V - | iba:Imgbuf | ibb:Imgbuf -- 30x30 - | | | V | ^ - | | +- 100x100 ,- 20x20 ,- 10x10 | | - | | | | ^ | ^ | | - | | `----------+----|---' | `--. ,--' - | | ,--------------' | | | - | | | ,------------------' | | - | | | | | | - | lca:ImgbufLSc lcb:ImgbufLSc - | (factor 1/10) (factor 1/10) - | \ / - | `-----------. ,-------------------' - | \ / - `------------------> scl:ImgbufGSc - (factor 1/10) diff --git a/doc/Makefile.am b/doc/Makefile.am index 7f627d09..7b40d0a2 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,51 +1,10 @@ dist_doc_DATA = user_help.html man_MANS = dillo.1 EXTRA_DIST = \ - index.doc \ - lout.doc \ - dw-map.doc \ - dw-overview.doc \ - dw-usage.doc \ - dw-layout-views.doc \ - dw-layout-widgets.doc \ - dw-widget-sizes.doc \ - dw-changes.doc \ - dw-images-and-backgrounds.doc \ - dw-dw-out-of-flow.doc \ - dw-dw-out-of-flow-2.doc \ - dw-stacking-context.doc \ - fltk-problems.doc \ - rounding-errors.doc \ - uml-legend.doc \ - dw-line-breaking.doc \ - dw-example-screenshot.png \ - dw-viewport-without-scrollbar.png \ - dw-viewport-with-scrollbar.png \ - dw-size-of-widget.png \ - dw-style-box-model.png \ - dw-style-length-absolute.png \ - dw-style-length-percentage.png \ - dw-style-length-relative.png \ - dw-textblock-collapsing-spaces-1-1.png \ - dw-textblock-collapsing-spaces-1-2.png \ - dw-textblock-collapsing-spaces-2-1.png \ - dw-textblock-collapsing-spaces-2-2.png \ - dw-floats-01.png \ - not-so-simple-container.png \ - Cache.txt \ - Cookies.txt \ - Dillo.txt \ - Dw.txt \ - HtmlParser.txt \ - IO.txt \ - Images.txt \ - Imgbuf.txt \ - NC_design.txt \ - Selection.txt \ - Dpid.txt \ - CCCwork.txt \ README \ - dillo.1.in + Cookies.txt \ + dillo.1.in \ + user_help.html dillo.1: $(srcdir)/dillo.1.in Makefile sed 's%/usr/local%${prefix}%g' < $(srcdir)/dillo.1.in > dillo.1 @@ -1,51 +1,5 @@ -README: Last update Jul 2009 +Last update: June 2015 -These documents cover dillo's internals. -For user help, see http://www.dillo.org/dillo3-help.html - --------------------------------------------------------------------------- - -These documents need a review. -*.txt were current with Dillo1, but many have since become more or - less out-of-date. -*.doc are doxygen source for the Dillo Widget (dw) component, and - were written for Dillo2. - -They will give you an overview of what's going on, but take them -with a pinch of salt. - - Of course I'd like to have *.txt as doxygen files too! -If somebody wants to make this conversion, please let me know -to assign higher priority to updating these docs. - --- -Jorge.- - - -------------------------------------------------------------------------- - FILE DESCRIPTION STATE - -------------------------------------------------------------------------- - NC_design.txt Naming&Coding design (Be sure to Current - read it before any other doc) - Dillo.txt General overview of the program Current - IO.txt Extensive introduction Current - Cache.txt Informative description Current - Images.txt Image handling and processing Current - HtmlParser.txt A versatile parser Current - Dw.txt The New Dillo Widget (Overview) Current - Imgbuf.txt Image buffers Pending - Selection.txt Selections, and link activation Current (?) - Cookies.txt Explains how to enable cookies Current - Dpid.txt Dillo plugin daemon Current - -------------------------------------------------------------------------- - - - * BTW, there's a small program (srch) within the src/ dir. It searches - tokens within the whole code (*.[ch]). It has proven very useful. - Ex: ./srch a_Image_write - ./srch todo: - - * Please submit your patches with 'hg diff'. - - - Happy coding! - --Jcid +This directory contains user documentation. Developer documentation is +only stored in the Hg repository at <http://hg.dillo.org/dillo/>, in +the directory "devdoc", but not part of the tarball. diff --git a/doc/Selection.txt b/doc/Selection.txt deleted file mode 100644 index 7904bd94..00000000 --- a/doc/Selection.txt +++ /dev/null @@ -1,149 +0,0 @@ -Apr 2003, S.Geerken@ping.de -Last update: Dec 2004 - -========= -Selection -========= - -The selection module (selection.[ch]) handles selections, as well as -activation of links, which is closely related. - - -General Overview -================ - -The selection module defines a structure "Selection", which is -associated to GtkDwViewport, and so to a widget tree. The selection -state is controlled by "abstract events", which are sent by single -widgets by calling one of the following functions: - - a_Selection_button_press for button press events, - a_Selection_button_release for button release events, and - a_Selection_button_motion for motion events (with pressed mouse - button). - -The widget must construct simple iterators (DwIterator), which will be -transferred to extended iterators (DwExtIterator), see below for more -details. All event handling functions have the same signature, the -arguments in detail are: - - - DwIterator *it the iterator pointing on the item under - the mouse pointer, - - gint char_pos the exact (character) position within - the iterator, - - gint link if this item is associated with a link, - its number (see DwImage, section - "signals" for the meaning), otherwise - -1, - - GdkEventButton *event the event itself; only the button is - used, - - gboolean within_content TRUE, if there is some selectable - content unter the mouse cursor; if set - to FALSE, the "full screen" feature is - used on double click. - -In some cases, char_pos would be difficult to determine. E.g., when -the DwPage widget decides that the user is pointing on a position -_at_the_end_ of an image (DwImage), it constructs a simple iterator -pointing on this image widget. In a simple iterator, that fact that -the pointer is at the end, would be represented by char_pos == 1. But -when transferring this simple iterator into an extended iterator, this -simple iterator is discarded and instead the stack has an iterator -pointing to text at the top. As a result, only the first letter of the -ALT text would be copied. - -To avoid this problem, widgets should in this case pass SELECTION_EOW -(end of word) as char_pos, which is then automatically reduced to the -actual length of the extended(!) iterator. - -The return value is the same as in DwWidget event handling methods. -I.e., in most cases, they should simply return it. The events -"link_pressed", "link_released" and "link_clicked" (but not -"link_entered") are emitted by these functions, so that widgets which -let the selection module handle links, should only emit "link_entered" -for themselves. (See DwImage.txt for a description of this.) - - -Selection State -=============== - -Selection interferes with handling the activation of links, so the -latter is also handled by the selection module. Details are based on -following guidelines: - - 1. It should be simple to select links and to start selection in - links. The rule to distinguish between link activation and - selection is that the selection starts as soon as the user leaves - the link. (This is, IMO, a useful feature. Even after drag and - drop has been implemented in dillo, this should be somehow - preserved.) - - 2. The selection should stay as long as possible, i.e., the old - selection is only cleared when a new selection is started. - -The latter leads to a model with two states: the selection state and -the link handling state. - -The general selection works, for events not pointing on links, like -this (numbers in parantheses after the event denote the button, "n" -means arbitrary button): - - motion(1) - ,-----. - | | - press(1) on non-link V | - NONE -----------------------> SELECTING <----------------. - ^ | | - | | release(1) | - | | | press(1) - | no V yes | - `----------------------- Anything selected? --------> SELECTED - -The selected region is represented by two DwExtIterators. - -Links are handled by a different state machine: - - ,-----------------------------. - | | - | Switch to selection - | (SELECTING) for n == 1. - | ^ - | | no - | | yes - | Still the same link? --. - | ^ | - | | | - | | motion(n) | - V press(n) on links | | - NONE ---------------------> PRESSED(n) <-----' - ^ | - | | release(n) - | | - | V yes - | Still the same link? -----------------. - | | | - | | no V - | V Send "clicked" signal. - | Switch to selection | - | (SELECTED) for n == 1. | - | | | - |`----------------------------' | - | | - `----------------------------------------------------------' - -Switching to selection simply means that the selection state will -eventually be SELECTED/SELECTING, with the original and the actual -position making up the selection region. This happens for button 1, -events with buttons other than 1 do not affect selection at all. - - -TODO -==== - -* a_Selection_button_motion currently always assumes that button 1 has - been pressed (since otherwise it would not do anything). This should - be made a bit cleaner. - -* The selection should be cleared, when the user selects something - somewhere else (perhaps switched into "non-active" mode, as some - Gtk+ widgets do). diff --git a/doc/dillo.1.in b/doc/dillo.1.in index 3bb5fe03..0853e6eb 100644 --- a/doc/dillo.1.in +++ b/doc/dillo.1.in @@ -1,4 +1,4 @@ -.TH dillo 1 "December 20, 2014" "" "USER COMMANDS" +.TH dillo 1 "May 28, 2015" "" "USER COMMANDS" .SH NAME dillo \- web browser .SH SYNOPSIS @@ -11,7 +11,7 @@ dillo \- web browser Dillo is a lightweight graphical web browser that aims to be secure. It handles HTTP internally, and FILE, FTP, and DATA URIs are handled through a plugin system (dpi). In addition, -.I INSECURE +.I EXPERIMENTAL HTTPS support can be enabled. Both FTP and Dillo's download manager use the .BR wget (1) downloader. @@ -68,7 +68,7 @@ Error in command line arguments. User's home directory. .TP .B http_proxy -URL of proxy to send HTTP traffic through. +URL of proxy to send HTTP/HTTPS traffic through. .SH FILES .TP .I dpid diff --git a/doc/not-so-simple-container.png b/doc/not-so-simple-container.png Binary files differdeleted file mode 100644 index 0af067b5..00000000 --- a/doc/not-so-simple-container.png +++ /dev/null diff --git a/dpi/cookies.c b/dpi/cookies.c index b858bd53..51767241 100644 --- a/dpi/cookies.c +++ b/dpi/cookies.c @@ -1142,14 +1142,14 @@ static int Cookies_set(char *cookie_string, char *url_host, * Compare the cookie with the supplied data to see whether it matches */ static bool_t Cookies_match(CookieData_t *cookie, const char *url_path, - bool_t host_only_val, bool_t is_ssl) + bool_t host_only_val, bool_t is_tls) { if (cookie->host_only != host_only_val) return FALSE; /* Insecure cookies match both secure and insecure urls, secure cookies match only secure urls */ - if (cookie->secure && !is_ssl) + if (cookie->secure && !is_tls) return FALSE; if (!Cookies_path_matches(url_path, cookie->path)) @@ -1163,7 +1163,7 @@ static void Cookies_add_matching_cookies(const char *domain, const char *url_path, bool_t host_only_val, Dlist *matching_cookies, - bool_t is_ssl) + bool_t is_tls) { DomainNode *node = dList_find_sorted(domains, domain, Domain_node_by_domain_cmp); @@ -1183,7 +1183,7 @@ static void Cookies_add_matching_cookies(const char *domain, --i; continue; } /* Check if the cookie matches the requesting URL */ - if (Cookies_match(cookie, url_path, host_only_val, is_ssl)) { + if (Cookies_match(cookie, url_path, host_only_val, is_tls)) { int j; CookieData_t *curr; uint_t path_length = strlen(cookie->path); @@ -1213,7 +1213,7 @@ static char *Cookies_get(char *url_host, char *url_path, char *domain_str, *str; CookieData_t *cookie; Dlist *matching_cookies; - bool_t is_ssl, is_ip_addr, host_only_val; + bool_t is_tls, is_ip_addr, host_only_val; Dstr *cookie_dstring; int i; @@ -1224,7 +1224,7 @@ static char *Cookies_get(char *url_host, char *url_path, matching_cookies = dList_new(8); /* Check if the protocol is secure or not */ - is_ssl = (!dStrAsciiCasecmp(url_scheme, "https")); + is_tls = (!dStrAsciiCasecmp(url_scheme, "https")); is_ip_addr = Cookies_domain_is_ip(url_host); @@ -1240,17 +1240,17 @@ static char *Cookies_get(char *url_host, char *url_path, /* e.g., sub.example.com set a cookie with domain ".sub.example.com". */ domain_str = dStrconcat(".", url_host, NULL); Cookies_add_matching_cookies(domain_str, url_path, host_only_val, - matching_cookies, is_ssl); + matching_cookies, is_tls); dFree(domain_str); } host_only_val = TRUE; /* e.g., sub.example.com set a cookie with no domain attribute. */ Cookies_add_matching_cookies(url_host, url_path, host_only_val, - matching_cookies, is_ssl); + matching_cookies, is_tls); host_only_val = FALSE; /* e.g., sub.example.com set a cookie with domain "sub.example.com". */ Cookies_add_matching_cookies(url_host, url_path, host_only_val, - matching_cookies, is_ssl); + matching_cookies, is_tls); if (!is_ip_addr) { for (domain_str = strchr(url_host+1, '.'); @@ -1258,12 +1258,12 @@ static char *Cookies_get(char *url_host, char *url_path, domain_str = strchr(domain_str+1, '.')) { /* e.g., sub.example.com set a cookie with domain ".example.com". */ Cookies_add_matching_cookies(domain_str, url_path, host_only_val, - matching_cookies, is_ssl); + matching_cookies, is_tls); if (domain_str[1]) { domain_str++; /* e.g., sub.example.com set a cookie with domain "example.com".*/ Cookies_add_matching_cookies(domain_str, url_path, host_only_val, - matching_cookies, is_ssl); + matching_cookies, is_tls); } } } diff --git a/dpi/vsource.c b/dpi/vsource.c index 2f1129cb..9d5694b5 100644 --- a/dpi/vsource.c +++ b/dpi/vsource.c @@ -3,7 +3,7 @@ * * This server is an example. Play with it and modify to your taste. * - * Copyright 2010 Jorge Arellano Cid <jcid@dillo.org> + * Copyright 2010-2015 Jorge Arellano Cid <jcid@dillo.org> * * 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 @@ -25,7 +25,7 @@ * Debugging macros */ #define _MSG(...) -#define MSG(...) printf("[vsource dpi]: " __VA_ARGS__) +#define MSG(...) fprintf(stderr, "[vsource dpi]: " __VA_ARGS__) /*---------------------------------------------------------------------------*/ @@ -42,38 +42,41 @@ void send_dpip_tag(Dsh *sh, char *dpip_tag) /* * Send source as plain text + * (handles embedded null chars correctly). */ void send_plain_text(Dsh *sh, int data_size) { - int bytes_read = 0; - char *src_str; + char *token; + int bytes_read = 0, token_size; /* Send HTTP header for plain text MIME type */ a_Dpip_dsh_write_str(sh, 0, "Content-type: text/plain\n\n"); while (bytes_read < data_size && - (src_str = a_Dpip_dsh_read_token(sh, 1))) { - bytes_read += strlen(src_str); - a_Dpip_dsh_write_str(sh, 1, src_str); - dFree(src_str); + (token = a_Dpip_dsh_read_token2(sh, 1, &token_size))) { + bytes_read += token_size; + _MSG("data_size=%d bytes_read=%d\n", data_size, bytes_read); + a_Dpip_dsh_write(sh, 1, token, token_size); + dFree(token); } } /* * Send source as plain text with line numbers + * (handles embedded null chars correctly). */ void send_numbered_text(Dsh *sh, int data_size) { - int bytes_read = 0, line = 1; - char *p, *q, *src_str, line_str[32]; + int bytes_read = 0, line = 1, token_size = 0; + char *p, *q, *token, line_str[32]; /* Send HTTP header for plain text MIME type */ a_Dpip_dsh_write_str(sh, 0, "Content-type: text/plain\n\n"); while (bytes_read < data_size && - (src_str = a_Dpip_dsh_read_token(sh, 1))) { - bytes_read += strlen(src_str); - p = q = src_str; + (token = a_Dpip_dsh_read_token2(sh, 1, &token_size))) { + bytes_read += token_size; + p = q = token; while (*p) { snprintf(line_str, 32, "%2d: ", line); @@ -84,28 +87,30 @@ void send_numbered_text(Dsh *sh, int data_size) ++p; ++line; } else { - a_Dpip_dsh_write_str(sh, 1, q); + /* send all the rest */ + a_Dpip_dsh_write(sh, 1, q, token_size - (q - token)); break; } q = ++p; } - dFree(src_str); + dFree(token); } } /* * Send source as html text with line numbers + * (handles embedded null chars correctly). */ void send_html_text(Dsh *sh, const char *url, int data_size) { - int bytes_read = 0, old_line = 0, line = 1; - char *p, *q, *src_str, line_str[128]; + int bytes_read = 0, old_line = 0, line = 1, token_size = 0; + char *p, *q, *token, line_str[128]; if (dStrnAsciiCasecmp(url, "dpi:", 4) == 0 && strncmp(url+4, "/vsource/:", 10) == 0) url += 14; - /* Send HTTP header for plain text MIME type */ + /* Send HTTP header for html text MIME type */ a_Dpip_dsh_write_str(sh, 0, "Content-type: text/html\n\n"); a_Dpip_dsh_write_str(sh, 0, DOCTYPE); @@ -113,23 +118,25 @@ void send_html_text(Dsh *sh, const char *url, int data_size) "\n" "<html><head>\n" "<title>Source for %s</title>\n" - "<style type=\"text/css\">PRE {white-space: pre-wrap}\n" + "<style type=\"text/css\">\n" + " body {white-space: pre-wrap; font-family: monospace}\n" + " td.r1 {background-color:#B87333}\n" + " td.r2 {background-color:#DD7F32}\n" "</style>\n" "</head>\n" "<body id=\"dillo_vs\">\n<table cellpadding='0'>\n", url); while (bytes_read < data_size && - (src_str = a_Dpip_dsh_read_token(sh, 1))) { - bytes_read += strlen(src_str); - p = q = src_str; + (token = a_Dpip_dsh_read_token2(sh, 1, &token_size))) { + bytes_read += token_size; + p = q = token; while (*p) { if (line > old_line) { snprintf(line_str, 128, - "%s<tr><td bgcolor='%s'>%d%s<td><pre>", - (line > 1) ? "</pre>" : "", - (line & 1) ? "#B87333" : "#DD7F32", line, - (line == 1 || (line % 10) == 0) ? " " : ""); + "<tr><td class='%s'>%d%s<td>", + (line & 1) ? "r1" : "r2", line, + (line == 1 || (line % 10) == 0) ? " " : ""); a_Dpip_dsh_write_str(sh, 0, line_str); old_line = line; } @@ -143,17 +150,16 @@ void send_html_text(Dsh *sh, const char *url, int data_size) a_Dpip_dsh_write(sh, 0, q, p - q); a_Dpip_dsh_write_str(sh, 0, (*p == '<') ? "<" : "&"); } - } else { - a_Dpip_dsh_write_str(sh, 1, q); + } else { + /* send all the rest */ + a_Dpip_dsh_write(sh, 1, q, token_size - (q - token)); break; } q = ++p; } - dFree(src_str); + dFree(token); } - if (data_size > 0) - a_Dpip_dsh_write_str(sh, 0, "</pre>"); a_Dpip_dsh_write_str(sh, 1, "</table></body></html>"); } @@ -194,7 +200,7 @@ int main(void) * asking from us. a_Dpip_dsh_read_token() will block and return * a full dpip token or null on error (it's commented in dpip.c) */ dpip_tag = a_Dpip_dsh_read_token(sh, 1); - MSG("tag = [%s]\n", dpip_tag); + _MSG("tag = [%s]\n", dpip_tag); /* Now that we have the dpip_tag, let's isolate the command and url */ cmd = a_Dpip_get_attr(dpip_tag, "cmd"); diff --git a/dpid/dpid_common.h b/dpid/dpid_common.h index cc7505a9..6df55ae1 100644 --- a/dpid/dpid_common.h +++ b/dpid/dpid_common.h @@ -18,7 +18,6 @@ */ #define _MSG(...) #define MSG(...) printf("[dpid]: " __VA_ARGS__) -#define _MSG_ERR(...) #define MSG_ERR(...) fprintf(stderr, "[dpid]: " __VA_ARGS__) #define dotDILLO_DPI ".dillo/dpi" diff --git a/dpip/dpip.c b/dpip/dpip.c index f4ce1bf0..2906ba2a 100644 --- a/dpip/dpip.c +++ b/dpip/dpip.c @@ -1,7 +1,7 @@ /* * File: dpip.c * - * Copyright 2005-2007 Jorge Arellano Cid <jcid@dillo.org> + * Copyright 2005-2015 Jorge Arellano Cid <jcid@dillo.org> * * 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 @@ -427,11 +427,13 @@ static void Dpip_dsh_read(Dsh *dsh, int blocking) /* * Return a newlly allocated string with the next dpip token in the socket. - * Return value: token string on success, NULL otherwise + * Return value: token string and length on success, NULL otherwise. + * (useful for handling null characters in the data stream) */ -char *a_Dpip_dsh_read_token(Dsh *dsh, int blocking) +char *a_Dpip_dsh_read_token2(Dsh *dsh, int blocking, int *DataSize) { char *p, *ret = NULL; + *DataSize = 0; /* Read all available data without blocking */ Dpip_dsh_read(dsh, 0); @@ -462,6 +464,7 @@ char *a_Dpip_dsh_read_token(Dsh *dsh, int blocking) /* return a full tag */ if ((p = strstr(dsh->rdbuf->str, DPIP_TAG_END))) { ret = dStrndup(dsh->rdbuf->str, p - dsh->rdbuf->str + 3); + *DataSize = p - dsh->rdbuf->str + 3; dStr_erase(dsh->rdbuf, 0, p - dsh->rdbuf->str + 3); if (strstr(ret, DPIP_MODE_SWITCH_TAG)) dsh->mode |= DPIP_LAST_TAG; @@ -470,6 +473,7 @@ char *a_Dpip_dsh_read_token(Dsh *dsh, int blocking) /* raw mode, return what we have "as is" */ if (dsh->rdbuf->len > 0) { ret = dStrndup(dsh->rdbuf->str, dsh->rdbuf->len); + *DataSize = dsh->rdbuf->len; dStr_truncate(dsh->rdbuf, 0); } } @@ -478,6 +482,17 @@ char *a_Dpip_dsh_read_token(Dsh *dsh, int blocking) } /* + * Return a newlly allocated string with the next dpip token in the socket. + * Return value: token string on success, NULL otherwise + */ +char *a_Dpip_dsh_read_token(Dsh *dsh, int blocking) +{ + int token_size; + + return a_Dpip_dsh_read_token2(dsh, blocking, &token_size); +} + +/* * Close this socket for reading and writing. * (flush pending data) */ diff --git a/dpip/dpip.h b/dpip/dpip.h index 1a1846df..a63eb658 100644 --- a/dpip/dpip.h +++ b/dpip/dpip.h @@ -70,6 +70,7 @@ int a_Dpip_dsh_write_str(Dsh *dsh, int flush, const char *str); int a_Dpip_dsh_tryflush(Dsh *dsh); int a_Dpip_dsh_trywrite(Dsh *dsh, const char *Data, int DataSize); char *a_Dpip_dsh_read_token(Dsh *dsh, int blocking); +char *a_Dpip_dsh_read_token2(Dsh *dsh, int blocking, int *DataSize); void a_Dpip_dsh_close(Dsh *dsh); void a_Dpip_dsh_free(Dsh *dsh); diff --git a/dw/table.cc b/dw/table.cc index 460e9a29..8b8fe853 100644 --- a/dw/table.cc +++ b/dw/table.cc @@ -907,7 +907,7 @@ void Table::actuallyCalcCellSizes (bool calcHeights) int childHeight; core::Extremes extremes; - // Will also call calcColumnExtremes(), when needed. + // Will also call forceCalcColumnExtremes(), when needed. getExtremes (&extremes); int availWidth = getAvailWidth (true); @@ -1285,24 +1285,6 @@ void Table::apportionRowSpan () /** - * \brief Fills dw::Table::colExtremes, only if recalculation is necessary. - * - * \bug Some parts are missing. - */ -void Table::_unused_calcColumnExtremes () -{ - // This method is actually not used. Consider removal. - - DBG_OBJ_ENTER0 ("resize", 0, "calcColumnExtremes"); - - if (extremesChanged () || extremesQueued ()) - forceCalcColumnExtremes (); - - DBG_OBJ_LEAVE (); -} - - -/** * \brief Fills dw::Table::colExtremes in all cases. */ void Table::forceCalcColumnExtremes () diff --git a/dw/table.hh b/dw/table.hh index c94514c0..b4f6a7bc 100644 --- a/dw/table.hh +++ b/dw/table.hh @@ -43,29 +43,26 @@ namespace dw { * sizeRequestImpl [color="#0000ff", URL="\ref dw::Table::sizeRequestImpl"]; * sizeAllocateImpl [color="#0000ff", * URL="\ref dw::Table::sizeAllocateImpl"]; + * getExtremes [color="#0000ff", URL="\ref dw::core::Widget::getExtremes"]; * getExtremesImpl [color="#0000ff", URL="\ref dw::Table::getExtremesImpl"]; * - * subgraph cluster_sizes { - * style="dashed"; color="#8080c0"; - * calcCellSizes [URL="\ref dw::Table::calcCellSizes"]; - * forceCalcCellSizes [URL="\ref dw::Table::forceCalcCellSizes"]; - * } - * - * subgraph cluster_extremes { - * style="dashed"; color="#8080c0"; - * calcColumnExtremes [URL="\ref dw::Table::calcColumnExtremes"]; - * forceCalcColumnExtremes[URL="\ref dw::Table::forceCalcColumnExtremes"]; - * } + * calcCellSizes [label="calcCellSizes (calcHeights = true)", + * URL="\ref dw::Table::calcCellSizes"]; + * forceCalcCellSizes [label="forceCalcCellSizes (calcHeights = true)", + * URL="\ref dw::Table::forceCalcCellSizes"]; + * actuallyCalcCellSizes[label="actuallyCalcCellSizes (calcHeights = true)", + * URL="\ref dw::Table::actuallyCalcCellSizes"]; + * forceCalcColumnExtremes[URL="\ref dw::Table::forceCalcColumnExtremes"]; * * sizeRequestImpl -> forceCalcCellSizes [label="[B]"]; * sizeAllocateImpl -> calcCellSizes [label="[A]"]; * getExtremesImpl -> forceCalcColumnExtremes [label="[B]"]; * - * forceCalcCellSizes -> calcColumnExtremes; + * forceCalcCellSizes -> actuallyCalcCellSizes; + * actuallyCalcCellSizes-> getExtremes; + * getExtremes -> getExtremesImpl [style="dashed", label="[C]"]; * * calcCellSizes -> forceCalcCellSizes [style="dashed", label="[C]"]; - * calcColumnExtremes -> forceCalcColumnExtremes [style="dashed", - * label="[C]"]; * } * \enddot * @@ -78,6 +75,12 @@ namespace dw { * [C] Whether this function is called, depends on NEEDS_RESIZE / * RESIZE_QUEUED / EXTREMES_CHANGED / EXTREMES_QUEUED. * + * **TODO:** + * + * - Are <tt>*[cC]alcCellSizes (calcHeights = *false*)</tt> not + * necessary anymore? + * - Calculating available sizes (Table::getAvailWidthOfChild) should + * be documented in this diagram, too. * * <h4>Apportionment</h4> * @@ -437,7 +440,6 @@ private: void actuallyCalcCellSizes (bool calcHeights); void apportionRowSpan (); - void _unused_calcColumnExtremes (); void forceCalcColumnExtremes (); void calcExtremesSpanMultiCols (int col, int cs, core::Extremes *cellExtremes, @@ -13,7 +13,6 @@ */ #define _MSG(...) #define _MSG_WARN(...) -#define _MSG_ERR(...) #define MSG(...) \ diff --git a/src/IO/IO.c b/src/IO/IO.c index e5c5fc79..0cdb9499 100644 --- a/src/IO/IO.c +++ b/src/IO/IO.c @@ -21,7 +21,7 @@ #include "../klist.h" #include "IO.h" #include "iowatch.hh" -#include "ssl.h" +#include "tls.h" /* * Symbolic defines for shutdown() function @@ -163,7 +163,7 @@ static bool_t IO_read(IOData_t *io) ssize_t St; bool_t ret = FALSE; int io_key = io->Key; - void *conn = a_Ssl_connection(io->FD); + void *conn = a_Tls_connection(io->FD); _MSG(" IO_read\n"); @@ -172,7 +172,7 @@ static bool_t IO_read(IOData_t *io) io->Status = 0; while (1) { - St = conn ? a_Ssl_read(conn, Buf, IOBufLen) + St = conn ? a_Tls_read(conn, Buf, IOBufLen) : read(io->FD, Buf, IOBufLen); if (St > 0) { dStr_append_l(io->Buf, Buf, St); @@ -217,13 +217,13 @@ static bool_t IO_write(IOData_t *io) { ssize_t St; bool_t ret = FALSE; - void *conn = a_Ssl_connection(io->FD); + void *conn = a_Tls_connection(io->FD); _MSG(" IO_write\n"); io->Status = 0; while (1) { - St = conn ? a_Ssl_write(conn, io->Buf->str, io->Buf->len) + St = conn ? a_Tls_write(conn, io->Buf->str, io->Buf->len) : write(io->FD, io->Buf->str, io->Buf->len); if (St < 0) { /* Error */ diff --git a/src/IO/Makefile.am b/src/IO/Makefile.am index ff600521..d8fed40a 100644 --- a/src/IO/Makefile.am +++ b/src/IO/Makefile.am @@ -15,8 +15,8 @@ libDiof_a_SOURCES = \ about.c \ Url.h \ http.c \ - ssl.h \ - ssl.c \ + tls.h \ + tls.c \ dpi.c \ IO.c \ iowatch.cc \ diff --git a/src/IO/http.c b/src/IO/http.c index e5c459ee..379d51c1 100644 --- a/src/IO/http.c +++ b/src/IO/http.c @@ -27,7 +27,7 @@ #include <arpa/inet.h> /* for inet_ntop */ #include "IO.h" -#include "ssl.h" +#include "tls.h" #include "Url.h" #include "../msg.h" #include "../klist.h" @@ -52,18 +52,18 @@ D_STMT_START { \ static const int HTTP_SOCKET_USE_PROXY = 0x1; static const int HTTP_SOCKET_QUEUED = 0x2; static const int HTTP_SOCKET_TO_BE_FREED = 0x4; -static const int HTTP_SOCKET_SSL = 0x8; +static const int HTTP_SOCKET_TLS = 0x8; /* 'web' is just a reference (no need to deallocate it here). */ typedef struct { int SockFD; - uint_t connect_port; uint_t flags; DilloWeb *web; /* reference to client's web structure */ DilloUrl *url; Dlist *addr_list; /* Holds the DNS answer */ ChainLink *Info; /* Used for CCC asynchronous operations */ - char *connected_to; /* Used for per-host connection limit */ + char *connected_to; /* Used for per-server connection limit */ + uint_t connect_port; Dstr *https_proxy_reply; } SocketData_t; @@ -72,19 +72,23 @@ typedef struct { */ typedef struct { char *host; + uint_t port; + bool_t https; + int active_conns; + int running_the_queue; Dlist *queue; -} HostConnection_t; +} Server_t; typedef struct { int fd; int skey; } FdMapEntry_t; -static void Http_socket_enqueue(HostConnection_t *hc, SocketData_t* sock); -static HostConnection_t *Http_host_connection_get(const char *host); -static void Http_host_connection_remove(HostConnection_t *hc); -static void Http_connect_socket(ChainLink *Info, HostConnection_t *hc); +static void Http_socket_enqueue(Server_t *srv, SocketData_t* sock); +static Server_t *Http_server_get(const char *host, uint_t port, bool_t https); +static void Http_server_remove(Server_t *srv); +static void Http_connect_socket(ChainLink *Info); static char *Http_get_connect_str(const DilloUrl *url); static void Http_send_query(SocketData_t *S); static void Http_socket_free(int SKey); @@ -97,7 +101,7 @@ static Klist_t *ValidSocks = NULL; /* Active sockets list. It holds pointers to static DilloUrl *HTTP_Proxy = NULL; static char *HTTP_Proxy_Auth_base64 = NULL; static char *HTTP_Language_hdr = NULL; -static Dlist *host_connections; +static Dlist *servers; /* TODO: If fd_map will stick around in its present form (FDs and SocketData_t) * then consider whether having both this and ValidSocks is necessary. @@ -127,7 +131,7 @@ int a_Http_init(void) HTTP_Proxy_Auth_base64 = a_Misc_encode_base64(prefs.http_proxyuser); */ - host_connections = dList_new(5); + servers = dList_new(5); fd_map = dList_new(20); return 0; @@ -211,12 +215,14 @@ void a_Http_connect_done(int fd, bool_t success) if (fme && (sd = a_Klist_get_data(ValidSocks, fme->skey))) { ChainLink *info = sd->Info; + bool_t valid_web = a_Web_valid(sd->web); - if (success) { + if (success && valid_web) { a_Chain_bfcb(OpSend, info, &sd->SockFD, "FD"); Http_send_query(sd); } else { - MSG_BW(sd->web, 1, "Could not establish connection."); + if (valid_web) + MSG_BW(sd->web, 1, "Could not establish connection."); MSG("fd %d is done and failed\n", sd->SockFD); dClose(fd); Http_socket_free(VOIDP2INT(info->LocalKey)); /* free sd */ @@ -228,48 +234,56 @@ void a_Http_connect_done(int fd, bool_t success) } } -static void Http_socket_activate(HostConnection_t *hc, SocketData_t *sd) +static void Http_socket_activate(Server_t *srv, SocketData_t *sd) { - dList_remove(hc->queue, sd); + dList_remove(srv->queue, sd); sd->flags &= ~HTTP_SOCKET_QUEUED; - hc->active_conns++; - sd->connected_to = hc->host; + srv->active_conns++; + sd->connected_to = srv->host; } -static void Http_connect_queued_sockets(HostConnection_t *hc) +static void Http_connect_queued_sockets(Server_t *srv) { SocketData_t *sd; int i; + srv->running_the_queue++; + for (i = 0; - i < dList_length(hc->queue) && hc->active_conns < prefs.http_max_conns; + (i < dList_length(srv->queue) && + srv->active_conns < prefs.http_max_conns); i++) { - sd = dList_nth_data(hc->queue, i); + sd = dList_nth_data(srv->queue, i); - if (!(sd->flags & HTTP_SOCKET_TO_BE_FREED)) { - int connect_ready = SSL_CONNECT_READY; + if (sd->flags & HTTP_SOCKET_TO_BE_FREED) { + dList_remove(srv->queue, sd); + dFree(sd); + i--; + } else { + int connect_ready = TLS_CONNECT_READY; - if (sd->flags & HTTP_SOCKET_SSL) - connect_ready = a_Ssl_connect_ready(sd->url); + if (sd->flags & HTTP_SOCKET_TLS) + connect_ready = a_Tls_connect_ready(sd->url); - if (connect_ready == SSL_CONNECT_NEVER || !a_Web_valid(sd->web)) { + if (connect_ready == TLS_CONNECT_NEVER || !a_Web_valid(sd->web)) { int SKey = VOIDP2INT(sd->Info->LocalKey); Http_socket_free(SKey); - } else if (connect_ready == SSL_CONNECT_READY) { + } else if (connect_ready == TLS_CONNECT_READY) { i--; - Http_socket_activate(hc, sd); - Http_connect_socket(sd->Info, hc); + Http_socket_activate(srv, sd); + Http_connect_socket(sd->Info); } } - if (sd->flags & HTTP_SOCKET_TO_BE_FREED) { - dList_remove(hc->queue, sd); - dFree(sd); - i--; - } } - _MSG("Queue %s len %d\n", hc->host, dList_length(hc->queue)); + _MSG("Queue http%s://%s:%u len %d\n", srv->https ? "s" : "", srv->host, + srv->port, dList_length(srv->queue)); + + if (--srv->running_the_queue == 0) { + if (srv->active_conns == 0) + Http_server_remove(srv); + } } /* @@ -290,15 +304,14 @@ static void Http_socket_free(int SKey) } else { if (S->SockFD != -1) Http_fd_map_remove_entry(S->SockFD); - a_Ssl_reset_server_state(S->url); + a_Tls_reset_server_state(S->url); if (S->connected_to) { - a_Ssl_close_by_fd(S->SockFD); + a_Tls_close_by_fd(S->SockFD); - HostConnection_t *hc = Http_host_connection_get(S->connected_to); - hc->active_conns--; - Http_connect_queued_sockets(hc); - if (hc->active_conns == 0) - Http_host_connection_remove(hc); + Server_t *srv = Http_server_get(S->connected_to, S->connect_port, + (S->flags & HTTP_SOCKET_TLS)); + srv->active_conns--; + Http_connect_queued_sockets(srv); } a_Url_free(S->url); dFree(S); @@ -478,9 +491,9 @@ static void Http_send_query(SocketData_t *S) /* * Prepare an HTTPS connection. If necessary, tunnel it through a proxy. - * Then perform the SSL handshake. + * Then perform the TLS handshake. */ -static void Http_connect_ssl(ChainLink *info) +static void Http_connect_tls(ChainLink *info) { int SKey = VOIDP2INT(info->LocalKey); SocketData_t *S = a_Klist_get_data(ValidSocks, SKey); @@ -496,7 +509,7 @@ static void Http_connect_ssl(ChainLink *info) dFree(dbuf); dFree(connect_str); } else { - a_Ssl_handshake(S->SockFD, S->url); + a_Tls_handshake(S->SockFD, S->url); } } @@ -504,7 +517,7 @@ static void Http_connect_ssl(ChainLink *info) * This function is called after the DNS succeeds in solving a hostname. * Task: Finish socket setup and start connecting the socket. */ -static void Http_connect_socket(ChainLink *Info, HostConnection_t *hc) +static void Http_connect_socket(ChainLink *Info) { int i, status; SocketData_t *S; @@ -542,7 +555,7 @@ static void Http_connect_socket(ChainLink *Info, HostConnection_t *hc) sin->sin_port = htons(S->connect_port); memcpy(&sin->sin_addr, dh->data, (size_t)dh->alen); if (a_Web_valid(S->web) && (S->web->flags & WEB_RootUrl)) - MSG("Connecting to %s:%d\n", inet_ntoa(sin->sin_addr), + MSG("Connecting to %s:%u\n", inet_ntoa(sin->sin_addr), S->connect_port); break; } @@ -557,7 +570,7 @@ static void Http_connect_socket(ChainLink *Info, HostConnection_t *hc) memcpy(&sin6->sin6_addr, dh->data, dh->alen); inet_ntop(dh->af, dh->data, buf, sizeof(buf)); if (a_Web_valid(S->web) && (S->web->flags & WEB_RootUrl)) - MSG("Connecting to %s:%d\n", buf, S->connect_port); + MSG("Connecting to %s:%u\n", buf, S->connect_port); break; } #endif @@ -567,8 +580,8 @@ static void Http_connect_socket(ChainLink *Info, HostConnection_t *hc) if (status == -1 && errno != EINPROGRESS) { MSG("Http_connect_socket ERROR: %s\n", dStrerror(errno)); a_Http_connect_done(S->SockFD, FALSE); - } else if (S->flags & HTTP_SOCKET_SSL) { - Http_connect_ssl(Info); + } else if (S->flags & HTTP_SOCKET_TLS) { + Http_connect_tls(Info); } else { a_Http_connect_done(S->SockFD, TRUE); } @@ -658,7 +671,7 @@ static void Http_dns_cb(int Status, Dlist *addr_list, void *data) int SKey = VOIDP2INT(data); bool_t clean_up = TRUE; SocketData_t *S; - HostConnection_t *hc; + Server_t *srv; S = a_Klist_get_data(ValidSocks, SKey); if (S) { @@ -670,9 +683,10 @@ static void Http_dns_cb(int Status, Dlist *addr_list, void *data) /* Successful DNS answer; save the IP */ S->addr_list = addr_list; clean_up = FALSE; - hc = Http_host_connection_get(host); - Http_socket_enqueue(hc, S); - Http_connect_queued_sockets(hc); + srv = Http_server_get(host, S->connect_port, + (S->flags & HTTP_SOCKET_TLS)); + Http_socket_enqueue(srv, S); + Http_connect_queued_sockets(srv); } else { /* DNS wasn't able to resolve the hostname */ MSG_BW(S->web, 0, "ERROR: DNS can't resolve %s", host); @@ -718,7 +732,7 @@ static int Http_get(ChainLink *Info, void *Data1) S->connect_port = URL_PORT(url); S->url = a_Url_dup(S->web->url); if (!dStrAsciiCasecmp(URL_SCHEME(S->url), "https")) - S->flags |= HTTP_SOCKET_SSL; + S->flags |= HTTP_SOCKET_TLS; /* Let the user know what we'll do */ MSG_BW(S->web, 1, "DNS resolving %s", hostname); @@ -734,16 +748,18 @@ static int Http_get(ChainLink *Info, void *Data1) /* * Can the old socket's fd be reused for the new socket? * - * NOTE: old and new must come from the same HostConnection_t. + * NOTE: old and new must come from the same Server_t. * This is not built to accept arbitrary sockets. */ static bool_t Http_socket_reuse_compatible(SocketData_t *old, SocketData_t *new) { + /* + * If we are using TLS through a proxy, we need to ensure that old and new + * are going through to the same host:port. + */ if (a_Web_valid(new->web) && - old->connect_port == new->connect_port && - ((old->flags & HTTP_SOCKET_SSL) == (new->flags & HTTP_SOCKET_SSL)) && - ((old->flags & HTTP_SOCKET_SSL) == 0 || + ((old->flags & HTTP_SOCKET_TLS) == 0 || (old->flags & HTTP_SOCKET_USE_PROXY) == 0 || ((URL_PORT(old->url) == URL_PORT(new->url)) && !dStrAsciiCasecmp(URL_HOST(old->url), URL_HOST(new->url))))) @@ -760,11 +776,13 @@ static void Http_socket_reuse(int SKey) SocketData_t *new_sd, *old_sd = a_Klist_get_data(ValidSocks, SKey); if (old_sd) { - HostConnection_t *hc = Http_host_connection_get(old_sd->connected_to); - int i, n = dList_length(hc->queue); + Server_t *srv = Http_server_get(old_sd->connected_to, + old_sd->connect_port, + (old_sd->flags & HTTP_SOCKET_TLS)); + int i, n = dList_length(srv->queue); for (i = 0; i < n; i++) { - new_sd = dList_nth_data(hc->queue, i); + new_sd = dList_nth_data(srv->queue, i); if (!(new_sd->flags & HTTP_SOCKET_TO_BE_FREED) && Http_socket_reuse_compatible(old_sd, new_sd)) { @@ -773,11 +791,11 @@ static void Http_socket_reuse(int SKey) new_sd->SockFD = old_sd->SockFD; old_sd->connected_to = NULL; - hc->active_conns--; + srv->active_conns--; Http_socket_free(SKey); MSG("Reusing fd %d for %s\n", new_sd->SockFD,URL_STR(new_sd->url)); - Http_socket_activate(hc, new_sd); + Http_socket_activate(srv, new_sd); Http_fd_map_add_entry(new_sd); a_Http_connect_done(new_sd->SockFD, success); return; @@ -863,7 +881,7 @@ void a_Http_ccc(int Op, int Branch, int Dir, ChainLink *Info, sd->https_proxy_reply->str); dStr_free(sd->https_proxy_reply, 1); sd->https_proxy_reply = NULL; - a_Ssl_handshake(sd->SockFD, sd->url); + a_Tls_handshake(sd->SockFD, sd->url); } else { MSG_BW(sd->web, 1, "Can't connect through proxy to %s", URL_HOST(sd->url)); @@ -935,68 +953,77 @@ void a_Http_ccc(int Op, int Branch, int Dir, ChainLink *Info, * Add socket data to the queue. Pages/stylesheets/etc. have higher priority * than images. */ -static void Http_socket_enqueue(HostConnection_t *hc, SocketData_t* sock) +static void Http_socket_enqueue(Server_t *srv, SocketData_t* sock) { sock->flags |= HTTP_SOCKET_QUEUED; if ((sock->web->flags & WEB_Image) == 0) { - int i, n = dList_length(hc->queue); + int i, n = dList_length(srv->queue); for (i = 0; i < n; i++) { - SocketData_t *curr = dList_nth_data(hc->queue, i); + SocketData_t *curr = dList_nth_data(srv->queue, i); if (a_Web_valid(curr->web) && (curr->web->flags & WEB_Image)) { - dList_insert_pos(hc->queue, sock, i); + dList_insert_pos(srv->queue, sock, i); return; } } } - dList_append(hc->queue, sock); + dList_append(srv->queue, sock); } -static HostConnection_t *Http_host_connection_get(const char *host) +static Server_t *Http_server_get(const char *host, uint_t port, bool_t https) { int i; - HostConnection_t *hc; + Server_t *srv; - for (i = 0; i < dList_length(host_connections); i++) { - hc = (HostConnection_t*) dList_nth_data(host_connections, i); + for (i = 0; i < dList_length(servers); i++) { + srv = (Server_t*) dList_nth_data(servers, i); - if (dStrAsciiCasecmp(host, hc->host) == 0) - return hc; + if (port == srv->port && https == srv->https && + !dStrAsciiCasecmp(host, srv->host)) + return srv; } - hc = dNew0(HostConnection_t, 1); - hc->queue = dList_new(10); - hc->host = dStrdup(host); - dList_append(host_connections, hc); + srv = dNew0(Server_t, 1); + srv->queue = dList_new(10); + srv->running_the_queue = 0; + srv->host = dStrdup(host); + srv->port = port; + srv->https = https; + dList_append(servers, srv); - return hc; + return srv; } -static void Http_host_connection_remove(HostConnection_t *hc) +static void Http_server_remove(Server_t *srv) { - assert(dList_length(hc->queue) == 0); - dList_free(hc->queue); - dList_remove_fast(host_connections, hc); - dFree(hc->host); - dFree(hc); + SocketData_t *sd; + + while ((sd = dList_nth_data(srv->queue, 0))) { + dList_remove_fast(srv->queue, sd); + dFree(sd); + } + dList_free(srv->queue); + dList_remove_fast(servers, srv); + dFree(srv->host); + dFree(srv); } -static void Http_host_connection_remove_all() +static void Http_servers_remove_all() { - HostConnection_t *hc; + Server_t *srv; SocketData_t *sd; - while (dList_length(host_connections) > 0) { - hc = (HostConnection_t*) dList_nth_data(host_connections, 0); - while ((sd = dList_nth_data(hc->queue, 0))) { - dList_remove(hc->queue, sd); + while (dList_length(servers) > 0) { + srv = (Server_t*) dList_nth_data(servers, 0); + while ((sd = dList_nth_data(srv->queue, 0))) { + dList_remove(srv->queue, sd); dFree(sd); } - Http_host_connection_remove(hc); + Http_server_remove(srv); } - dList_free(host_connections); + dList_free(servers); } static void Http_fd_map_remove_all() @@ -1017,7 +1044,7 @@ static void Http_fd_map_remove_all() */ void a_Http_freeall(void) { - Http_host_connection_remove_all(); + Http_servers_remove_all(); Http_fd_map_remove_all(); a_Klist_free(&ValidSocks); a_Url_free(HTTP_Proxy); diff --git a/src/IO/ssl.h b/src/IO/ssl.h deleted file mode 100644 index f55479b2..00000000 --- a/src/IO/ssl.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef __SSL_H__ -#define __SSL_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "../url.h" - -#define SSL_CONNECT_NEVER -1 -#define SSL_CONNECT_NOT_YET 0 -#define SSL_CONNECT_READY 1 - -void a_Ssl_init(); - - -#ifdef ENABLE_SSL -int a_Ssl_connect_ready(const DilloUrl *url); -void a_Ssl_reset_server_state(const DilloUrl *url); - -/* Use to initiate a SSL connection. */ -void a_Ssl_handshake(int fd, const DilloUrl *url); - -void *a_Ssl_connection(int fd); - -void a_Ssl_freeall(); - -void a_Ssl_close_by_fd(int fd); -int a_Ssl_read(void *conn, void *buf, size_t len); -int a_Ssl_write(void *conn, void *buf, size_t len); -#else - -#define a_Ssl_connect_ready(url) SSL_CONNECT_NEVER -#define a_Ssl_reset_server_state(url) ; -#define a_Ssl_handshake(fd, url) ; -#define a_Ssl_connection(fd) NULL -#define a_Ssl_freeall() ; -#define a_Ssl_close_by_fd(fd) ; -#define a_Ssl_read(conn, buf, len) 0 -#define a_Ssl_write(conn, buf, len) 0 -#endif -#ifdef __cplusplus -} -#endif - -#endif /* __SSL_H__ */ - diff --git a/src/IO/ssl.c b/src/IO/tls.c index 856d94b5..f0f33215 100644 --- a/src/IO/ssl.c +++ b/src/IO/tls.c @@ -1,5 +1,5 @@ /* - * File: ssl.c + * File: tls.c * * Copyright 2004 Garrett Kajmowicz <gkajmowi@tbaytel.net> * (for some bits derived from the https dpi, e.g., certificate handling) @@ -33,9 +33,9 @@ #ifndef ENABLE_SSL -void a_Ssl_init() +void a_Tls_init() { - MSG("SSL: Disabled at compilation time.\n"); + MSG("TLS: Disabled at compilation time.\n"); } #else @@ -52,7 +52,7 @@ void a_Ssl_init() #include "../dialog.hh" #include "../klist.h" #include "iowatch.hh" -#include "ssl.h" +#include "tls.h" #include "Url.h" #include <openssl/ssl.h> @@ -78,7 +78,7 @@ typedef struct { } FdMapEntry_t; /* - * Data type for SSL connection information + * Data type for TLS connection information */ typedef struct { int fd; @@ -87,22 +87,22 @@ typedef struct { bool_t connecting; } Conn_t; -/* List of active SSL connections */ +/* List of active TLS connections */ static Klist_t *conn_list = NULL; /* - * If ssl_context is still NULL, this corresponds to SSL being disabled. + * If ssl_context is still NULL, this corresponds to TLS being disabled. */ static SSL_CTX *ssl_context; static Dlist *servers; static Dlist *fd_map; -static void Ssl_connect_cb(int fd, void *vssl); +static void Tls_connect_cb(int fd, void *vconnkey); /* * Compare by FD. */ -static int Ssl_fd_map_cmp(const void *v1, const void *v2) +static int Tls_fd_map_cmp(const void *v1, const void *v2) { int fd = VOIDP2INT(v2); const FdMapEntry_t *e = v1; @@ -110,14 +110,14 @@ static int Ssl_fd_map_cmp(const void *v1, const void *v2) return (fd != e->fd); } -static void Ssl_fd_map_add_entry(int fd, int connkey) +static void Tls_fd_map_add_entry(int fd, int connkey) { FdMapEntry_t *e = dNew0(FdMapEntry_t, 1); e->fd = fd; e->connkey = connkey; - if (dList_find_custom(fd_map, INT2VOIDP(e->fd), Ssl_fd_map_cmp)) { - MSG_ERR("SSL FD ENTRY ALREADY FOUND FOR %d\n", e->fd); + if (dList_find_custom(fd_map, INT2VOIDP(e->fd), Tls_fd_map_cmp)) { + MSG_ERR("TLS FD ENTRY ALREADY FOUND FOR %d\n", e->fd); assert(0); } @@ -128,30 +128,30 @@ static void Ssl_fd_map_add_entry(int fd, int connkey) /* * Remove and free entry from fd_map. */ -static void Ssl_fd_map_remove_entry(int fd) +static void Tls_fd_map_remove_entry(int fd) { - void *data = dList_find_custom(fd_map, INT2VOIDP(fd), Ssl_fd_map_cmp); + void *data = dList_find_custom(fd_map, INT2VOIDP(fd), Tls_fd_map_cmp); //MSG("REMOVE ENTRY %d\n", fd); if (data) { dList_remove_fast(fd_map, data); dFree(data); } else { - MSG("SSL FD ENTRY NOT FOUND FOR %d\n", fd); + MSG("TLS FD ENTRY NOT FOUND FOR %d\n", fd); } } /* - * Return SSL connection information for a given file - * descriptor, or NULL if no SSL connection was found. + * Return TLS connection information for a given file + * descriptor, or NULL if no TLS connection was found. */ -void *a_Ssl_connection(int fd) +void *a_Tls_connection(int fd) { Conn_t *conn; if (fd_map) { FdMapEntry_t *fme = dList_find_custom(fd_map, INT2VOIDP(fd), - Ssl_fd_map_cmp); + Tls_fd_map_cmp); if (fme && (conn = a_Klist_get_data(conn_list, fme->connkey))) return conn; @@ -160,9 +160,9 @@ void *a_Ssl_connection(int fd) } /* - * Add a new SSL connection information node. + * Add a new TLS connection information node. */ -static int Ssl_conn_new(int fd, const DilloUrl *url, SSL *ssl) +static int Tls_conn_new(int fd, const DilloUrl *url, SSL *ssl) { int key; @@ -174,19 +174,22 @@ static int Ssl_conn_new(int fd, const DilloUrl *url, SSL *ssl) key = a_Klist_insert(&conn_list, conn); - Ssl_fd_map_add_entry(fd, key); + Tls_fd_map_add_entry(fd, key); return key; } /* - * Let's monitor for ssl alerts. + * Let's monitor for TLS alerts. */ -static void Ssl_info_cb(const SSL *ssl, int where, int ret) +static void Tls_info_cb(const SSL *ssl, int where, int ret) { if (where & SSL_CB_ALERT) { - MSG("SSL ALERT on %s: %s\n", (where & SSL_CB_READ) ? "read" : "write", - SSL_alert_desc_string_long(ret)); + const char *str = SSL_alert_desc_string_long(ret); + + if (strcmp(str, "close notify")) + MSG("TLS ALERT on %s: %s\n", (where & SSL_CB_READ) ? "read" : "write", + str); } } @@ -197,7 +200,7 @@ static void Ssl_info_cb(const SSL *ssl, int where, int ret) * abysmal openssl documentation, this was worked out from reading discussion * on the web and then reading openssl source to see what it normally does. */ -static void Ssl_load_certificates() +static void Tls_load_certificates() { /* curl-7.37.1 says that the following bundle locations are used on "Debian * systems", "Redhat and Mandriva", "old(er) Redhat", "FreeBSD", and @@ -207,7 +210,7 @@ static void Ssl_load_certificates() */ uint_t u; char *userpath; - static const char *ca_files[] = { + static const char *const ca_files[] = { "/etc/ssl/certs/ca-certificates.crt", "/etc/pki/tls/certs/ca-bundle.crt", "/usr/share/ssl/certs/ca-bundle.crt", @@ -216,7 +219,7 @@ static void Ssl_load_certificates() CA_CERTS_FILE }; - static const char *ca_paths[] = { + static const char *const ca_paths[] = { "/etc/ssl/certs/", CA_CERTS_DIR }; @@ -247,7 +250,7 @@ static void Ssl_load_certificates() /* * Initialize the OpenSSL library. */ -void a_Ssl_init(void) +void a_Tls_init(void) { SSL_library_init(); SSL_load_error_strings(); @@ -266,7 +269,7 @@ void a_Ssl_init(void) return; } - SSL_CTX_set_info_callback(ssl_context, Ssl_info_cb); + SSL_CTX_set_info_callback(ssl_context, Tls_info_cb); /* Don't want: eNULL, which has no encryption; aNULL, which has no * authentication; LOW, which as of 2014 use 64 or 56-bit encryption; @@ -285,7 +288,7 @@ void a_Ssl_init(void) /* This lets us deal with self-signed certificates */ SSL_CTX_set_verify(ssl_context, SSL_VERIFY_NONE, NULL); - Ssl_load_certificates(); + Tls_load_certificates(); fd_map = dList_new(20); servers = dList_new(8); @@ -295,7 +298,7 @@ void a_Ssl_init(void) * Save certificate with a hashed filename. * Return: 0 on success, 1 on failure. */ -static int Ssl_save_certificate_home(X509 * cert) +static int Tls_save_certificate_home(X509 * cert) { char buf[4096]; @@ -338,16 +341,30 @@ static int Ssl_save_certificate_home(X509 * cert) } /* - * Test whether a URL corresponds to a server. + * Ordered comparison of servers. */ -static int Ssl_servers_cmp(const void *v1, const void *v2) +static int Tls_servers_cmp(const void *v1, const void *v2) { - Server_t *s = (Server_t *)v1; + const Server_t *s1 = (const Server_t *)v1, *s2 = (const Server_t *)v2; + int cmp = dStrAsciiCasecmp(s1->hostname, s2->hostname); + + if (!cmp) + cmp = s1->port - s2->port; + return cmp; +} +/* + * Ordered comparison of server with URL. + */ +static int Tls_servers_by_url_cmp(const void *v1, const void *v2) +{ + const Server_t *s = (const Server_t *)v1; const DilloUrl *url = (const DilloUrl *)v2; - const char *host = URL_HOST(url); - int port = URL_PORT(url); - return (dStrAsciiCasecmp(s->hostname, host) || (port != s->port)); + int cmp = dStrAsciiCasecmp(s->hostname, URL_HOST(url)); + + if (!cmp) + cmp = s->port - URL_PORT(url); + return cmp; } /* @@ -355,41 +372,31 @@ static int Ssl_servers_cmp(const void *v1, const void *v2) * Once we have the certificate, know whether we like it -- and whether the * user accepts it -- HTTP can run through queued sockets as normal. * - * Return: 1 means yes, 0 means not yet, -1 means never. - * TODO: Something clearer or different. + * Return: TLS_CONNECT_READY or TLS_CONNECT_NOT_YET or TLS_CONNECT_NEVER. */ -int a_Ssl_connect_ready(const DilloUrl *url) +int a_Tls_connect_ready(const DilloUrl *url) { Server_t *s; - int i, len; - const char *host = URL_HOST(url); - const int port = URL_PORT(url); - int ret = SSL_CONNECT_READY; + int ret = TLS_CONNECT_READY; - dReturn_val_if_fail(ssl_context, SSL_CONNECT_NEVER); + dReturn_val_if_fail(ssl_context, TLS_CONNECT_NEVER); - len = dList_length(servers); + if ((s = dList_find_sorted(servers, url, Tls_servers_by_url_cmp))) { + if (s->cert_status == CERT_STATUS_RECEIVING) + ret = TLS_CONNECT_NOT_YET; + else if (s->cert_status == CERT_STATUS_BAD) + ret = TLS_CONNECT_NEVER; - for (i = 0; i < len; i++) { - s = dList_nth_data(servers, i); - - if (!dStrAsciiCasecmp(s->hostname, host) && (port == s->port)) { - if (s->cert_status == CERT_STATUS_RECEIVING) - ret = SSL_CONNECT_NOT_YET; - else if (s->cert_status == CERT_STATUS_BAD) - ret = SSL_CONNECT_NEVER; + if (s->cert_status == CERT_STATUS_NONE) + s->cert_status = CERT_STATUS_RECEIVING; + } else { + s = dNew(Server_t, 1); - if (s->cert_status == CERT_STATUS_NONE) - s->cert_status = CERT_STATUS_RECEIVING; - return ret; - } + s->hostname = dStrdup(URL_HOST(url)); + s->port = URL_PORT(url); + s->cert_status = CERT_STATUS_RECEIVING; + dList_insert_sorted(servers, s, Tls_servers_cmp); } - s = dNew(Server_t, 1); - - s->port = port; - s->hostname = dStrdup(host); - s->cert_status = CERT_STATUS_RECEIVING; - dList_append(servers, s); return ret; } @@ -397,9 +404,9 @@ int a_Ssl_connect_ready(const DilloUrl *url) * Did we find problems with the certificate, and did the user proceed to * reject the connection? */ -static int Ssl_user_said_no(const DilloUrl *url) +static int Tls_user_said_no(const DilloUrl *url) { - Server_t *s = dList_find_custom(servers, url, Ssl_servers_cmp); + Server_t *s = dList_find_sorted(servers, url, Tls_servers_by_url_cmp); if (!s) return FALSE; @@ -407,20 +414,6 @@ static int Ssl_user_said_no(const DilloUrl *url) return s->cert_status == CERT_STATUS_BAD; } -/* - * Did we find problems with the certificate, and did the user proceed to - * accept the connection anyway? - */ -static int Ssl_user_said_yes(const DilloUrl *url) -{ - Server_t *s = dList_find_custom(servers, url, Ssl_servers_cmp); - - if (!s) - return FALSE; - - return s->cert_status == CERT_STATUS_USER_ACCEPTED; -} - /******************** BEGINNING OF STUFF DERIVED FROM wget-1.16.3 */ #define ASTERISK_EXCLUDES_DOT /* mandated by rfc2818 */ @@ -466,13 +459,18 @@ static bool_t pattern_match (const char *pattern, const char *string) return *n == '\0'; } -static bool_t Ssl_check_cert_hostname(X509 *cert, const DilloUrl *url, +/* + * Check that the certificate corresponds to the site it's presented for. + * + * Return TRUE if the hostname matched or the user indicated acceptance. + * FALSE on failure. + */ +static bool_t Tls_check_cert_hostname(X509 *cert, const char *host, int *choice) { - dReturn_val_if_fail(cert && url, -1); + dReturn_val_if_fail(cert && host, FALSE); char *msg; - const char *host = URL_HOST(url); GENERAL_NAMES *subjectAltNames; bool_t success = TRUE, alt_name_checked = FALSE;; char common_name[256]; @@ -493,6 +491,10 @@ static bool_t Ssl_check_cert_hostname(X509 *cert, const DilloUrl *url, { /* Test subject alternative names */ + Dstr *err = dStr_new(""); + dStr_sprintf(err, "Hostname %s does not match any of certificate's " + "Subject Alternative Names: ", host); + /* Do we want to check for dNSNAmes or ipAddresses (see RFC 2818)? * Signal it by host_in_octet_string. */ ASN1_OCTET_STRING *host_in_octet_string = a2i_IPADDRESS (host); @@ -516,6 +518,7 @@ static bool_t Ssl_check_cert_hostname(X509 *cert, const DilloUrl *url, if (!ASN1_STRING_cmp (host_in_octet_string, name->d.iPAddress)) break; + dStr_sprintfa(err, "%s ", name->d.iPAddress); } } else if (name->type == GEN_DNS) @@ -537,6 +540,7 @@ static bool_t Ssl_check_cert_hostname(X509 *cert, const DilloUrl *url, OPENSSL_free (name_in_utf8); break; } + dStr_sprintfa(err, "%s ", name_in_utf8); OPENSSL_free (name_in_utf8); } } @@ -549,11 +553,8 @@ static bool_t Ssl_check_cert_hostname(X509 *cert, const DilloUrl *url, if (alt_name_checked == TRUE && i >= numaltnames) { success = FALSE; - msg = dStrconcat("No certificate subject alternative name matches" - " requested host name \n", host, NULL); - *choice = a_Dialog_choice("Dillo SSL security warning", - msg, "Continue", "Cancel", NULL); - dFree(msg); + *choice = a_Dialog_choice("Dillo TLS security warning", + err->str, "Continue", "Cancel", NULL); switch (*choice){ case 1: @@ -565,6 +566,7 @@ static bool_t Ssl_check_cert_hostname(X509 *cert, const DilloUrl *url, break; } } + dStr_free(err, 1); } if (alt_name_checked == FALSE) @@ -580,7 +582,7 @@ static bool_t Ssl_check_cert_hostname(X509 *cert, const DilloUrl *url, success = FALSE; msg = dStrconcat("Certificate common name ", common_name, " doesn't match requested host name ", host, NULL); - *choice = a_Dialog_choice("Dillo SSL security warning", + *choice = a_Dialog_choice("Dillo TLS security warning", msg, "Continue", "Cancel", NULL); dFree(msg); @@ -626,7 +628,7 @@ static bool_t Ssl_check_cert_hostname(X509 *cert, const DilloUrl *url, "character). This may be an indication that the " "host is not who it claims to be -- that is, not " "the real ", host, NULL); - *choice = a_Dialog_choice("Dillo SSL security warning", + *choice = a_Dialog_choice("Dillo TLS security warning", msg, "Continue", "Cancel", NULL); dFree(msg); @@ -648,18 +650,58 @@ static bool_t Ssl_check_cert_hostname(X509 *cert, const DilloUrl *url, /******************** END OF STUFF DERIVED FROM wget-1.16.3 */ /* + * Get the certificate at the end of the chain, or NULL on failure. + * + * Rumor has it that the stack can be NULL if a connection has been reused + * and that the stack can then be reconstructed if necessary, but it doesn't + * sound like a case we'll encounter. + */ +static X509 *Tls_get_end_of_chain(SSL *ssl) +{ + STACK_OF(X509) *sk = SSL_get_peer_cert_chain(ssl); + + return sk ? sk_X509_value(sk, sk_X509_num(sk) - 1) : NULL; +} + +static void Tls_get_issuer_name(X509 *cert, char *buf, uint_t buflen) +{ + if (cert) { + X509_NAME_oneline(X509_get_issuer_name(cert), buf, buflen); + } else { + strncpy(buf, "(unknown)", buflen); + buf[buflen-1] = '\0'; + } +} + +static void Tls_get_expiration_str(X509 *cert, char *buf, uint_t buflen) +{ + ASN1_TIME *exp_date = X509_get_notAfter(cert); + BIO *b = BIO_new(BIO_s_mem()); + int rc = ASN1_TIME_print(b, exp_date); + + if (rc > 0) { + rc = BIO_gets(b, buf, buflen); + } + if (rc <= 0) { + strncpy(buf, "(unknown)", buflen); + buf[buflen-1] = '\0'; + } + BIO_free(b); +} + +/* * Examine the certificate, and, if problems are detected, ask the user what * to do. * Return: -1 if connection should be canceled, or 0 if it should continue. */ -static int Ssl_examine_certificate(SSL *ssl, const DilloUrl *url) +static int Tls_examine_certificate(SSL *ssl, Server_t *srv,const char *host) { X509 *remote_cert; long st; - char buf[4096], *cn, *msg; + const uint_t buflen = 4096; + char buf[buflen], *cn, *msg; int choice = -1, ret = -1; - char *title = dStrconcat("Dillo SSL security warning: ",URL_HOST(url),NULL); - Server_t *srv = dList_find_custom(servers, url, Ssl_servers_cmp); + char *title = dStrconcat("Dillo TLS security warning: ", host, NULL); remote_cert = SSL_get_peer_certificate(ssl); if (remote_cert == NULL){ @@ -674,7 +716,7 @@ static int Ssl_examine_certificate(SSL *ssl, const DilloUrl *url) ret = 0; } - } else if (Ssl_check_cert_hostname(remote_cert, url, &choice)) { + } else if (Tls_check_cert_hostname(remote_cert, host, &choice)) { /* Figure out if (and why) the remote system can't be trusted */ st = SSL_get_verify_result(ssl); switch (st) { @@ -713,7 +755,7 @@ static int Ssl_examine_certificate(SSL *ssl, const DilloUrl *url) /* Save certificate to a file here and recheck the chain */ /* Potential security problems because we are writing * to the filesystem */ - Ssl_save_certificate_home(remote_cert); + Tls_save_certificate_home(remote_cert); ret = 1; break; default: @@ -761,14 +803,15 @@ static int Ssl_examine_certificate(SSL *ssl, const DilloUrl *url) break; case X509_V_ERR_CERT_HAS_EXPIRED: case X509_V_ERR_CRL_HAS_EXPIRED: - choice = a_Dialog_choice(title, - "The remote certificate has expired. The certificate " - "wasn't designed to last this long. You should avoid " - "this site.", - "Continue", "Cancel", NULL); + Tls_get_expiration_str(remote_cert, buf, buflen); + msg = dStrconcat("The remote certificate expired on: ", buf, + ". This site can no longer be trusted.", NULL); + + choice = a_Dialog_choice(title, msg, "Continue", "Cancel", NULL); if (choice == 1) { ret = 0; } + dFree(msg); break; case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: @@ -812,23 +855,24 @@ static int Ssl_examine_certificate(SSL *ssl, const DilloUrl *url) } break; case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: - choice = a_Dialog_choice(title, - "Self signed certificate in certificate chain. The certificate " - "chain could be built up using the untrusted certificates but the " - "root could not be found locally.", - "Continue", "Cancel", NULL); + Tls_get_issuer_name(Tls_get_end_of_chain(ssl), buf, buflen); + msg = dStrconcat("Certificate chain led to a self-signed certificate " + "instead of a trusted root. Name: ", buf , NULL); + choice = a_Dialog_choice(title, msg, "Continue", "Cancel", NULL); if (choice == 1) { ret = 0; } + dFree(msg); break; case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: - choice = a_Dialog_choice(title, - "Unable to get local issuer certificate. The issuer certificate " - "of an untrusted certificate cannot be found.", - "Continue", "Cancel", NULL); + Tls_get_issuer_name(Tls_get_end_of_chain(ssl), buf, buflen); + msg = dStrconcat("The issuer certificate of an untrusted certificate " + "cannot be found. Issuer: ", buf, NULL); + choice = a_Dialog_choice(title, msg, "Continue", "Cancel", NULL); if (choice == 1) { ret = 0; } + dFree(msg); break; default: /* Need to add more options later */ snprintf(buf, 80, @@ -859,10 +903,10 @@ static int Ssl_examine_certificate(SSL *ssl, const DilloUrl *url) * If the connection was closed before we got the certificate, we need to * reset state so that we'll try again. */ -void a_Ssl_reset_server_state(const DilloUrl *url) +void a_Tls_reset_server_state(const DilloUrl *url) { if (servers) { - Server_t *s = dList_find_custom(servers, url, Ssl_servers_cmp); + Server_t *s = dList_find_sorted(servers, url, Tls_servers_by_url_cmp); if (s && s->cert_status == CERT_STATUS_RECEIVING) s->cert_status = CERT_STATUS_NONE; @@ -870,14 +914,14 @@ void a_Ssl_reset_server_state(const DilloUrl *url) } /* - * Close an open SSL connection. + * Close an open TLS connection. */ -static void Ssl_close_by_key(int connkey) +static void Tls_close_by_key(int connkey) { Conn_t *c; if ((c = a_Klist_get_data(conn_list, connkey))) { - a_Ssl_reset_server_state(c->url); + a_Tls_reset_server_state(c->url); if (c->connecting) { a_IOwatch_remove_fd(c->fd, -1); dClose(c->fd); @@ -886,24 +930,100 @@ static void Ssl_close_by_key(int connkey) SSL_free(c->ssl); a_Url_free(c->url); - Ssl_fd_map_remove_entry(c->fd); + Tls_fd_map_remove_entry(c->fd); a_Klist_remove(conn_list, connkey); dFree(c); } } +static void Tls_print_cert_chain(SSL *ssl) +{ + STACK_OF(X509) *sk = SSL_get_peer_cert_chain(ssl); + + if (sk) { + const uint_t buflen = 4096; + char buf[buflen]; + int rc, i, n = sk_X509_num(sk); + X509 *cert = NULL; + EVP_PKEY *public_key; + int key_type, key_bits; + const char *type_str; + BIO *b; + + for (i = 0; i < n; i++) { + cert = sk_X509_value(sk, i); + public_key = X509_get_pubkey(cert); + + /* We are trying to find a way to get the hash function used + * with a certificate. This way, which is not very pleasant, puts + * a string such as "sha256WithRSAEncryption" in our buffer and we + * then trim off the "With..." part. + */ + b = BIO_new(BIO_s_mem()); + rc = i2a_ASN1_OBJECT(b, cert->sig_alg->algorithm); + + if (rc > 0) { + rc = BIO_gets(b, buf, buflen); + } + if (rc <= 0) { + strcpy(buf, "(unknown)"); + buf[buflen-1] = '\0'; + } else { + char *s = strstr(buf, "With"); + + if (s) { + *s = '\0'; + if (!strcmp(buf, "sha1")) { + MSG_WARN("In 2015, browsers have begun to deprecate SHA1 " + "certificates.\n"); + } else if (!strncmp(buf, "md", 2)) { + MSG_ERR("Browsers stopped accepting MD5 certificates around " + "2012.\n"); + } + } + } + BIO_free(b); + MSG("%s ", buf); + + + key_type = EVP_PKEY_type(public_key->type); + type_str = key_type == EVP_PKEY_RSA ? "RSA" : + key_type == EVP_PKEY_DSA ? "DSA" : + key_type == EVP_PKEY_DH ? "DH" : + key_type == EVP_PKEY_EC ? "EC" : "???"; + key_bits = EVP_PKEY_bits(public_key); + X509_NAME_oneline(X509_get_subject_name(cert), buf, buflen); + buf[buflen-1] = '\0'; + MSG("%d-bit %s: %s\n", key_bits, type_str, buf); + EVP_PKEY_free(public_key); + + if (key_type == EVP_PKEY_RSA && key_bits <= 1024) { + /* TODO: Gather warnings into one popup. */ + MSG_WARN("In 2014/5, browsers have been deprecating 1024-bit RSA " + "keys.\n"); + } + } + + if (cert) { + X509_NAME_oneline(X509_get_issuer_name(cert), buf, buflen); + buf[buflen-1] = '\0'; + MSG("root: %s\n", buf); + } + } +} + /* * Connect, set a callback if it's still not completed. If completed, check * the certificate and report back to http. */ -static void Ssl_connect(int fd, int connkey) +static void Tls_connect(int fd, int connkey) { int ret; bool_t ongoing = FALSE, failed = TRUE; Conn_t *conn; if (!(conn = a_Klist_get_data(conn_list, connkey))) { - MSG("Ssl_connect: conn for fd %d not valid\n", fd); + MSG("Tls_connect: conn for fd %d not valid\n", fd); return; } @@ -917,10 +1037,10 @@ static void Ssl_connect(int fd, int connkey) err1_ret == SSL_ERROR_WANT_WRITE) { int want = err1_ret == SSL_ERROR_WANT_READ ? DIO_READ : DIO_WRITE; - _MSG("iowatching fd %d for ssl -- want %s\n", fd, + _MSG("iowatching fd %d for tls -- want %s\n", fd, err1_ret == SSL_ERROR_WANT_READ ? "read" : "write"); a_IOwatch_remove_fd(fd, -1); - a_IOwatch_add_fd(fd, want, Ssl_connect_cb, INT2VOIDP(connkey)); + a_IOwatch_add_fd(fd, want, Tls_connect_cb, INT2VOIDP(connkey)); ongoing = TRUE; failed = FALSE; } else if (err1_ret == SSL_ERROR_SYSCALL || err1_ret == SSL_ERROR_SSL) { @@ -934,14 +1054,14 @@ static void Ssl_connect(int fd, int connkey) } else { /* nothing in the error queue */ if (ret == 0) { - MSG("SSL connect error: \"an EOF was observed that violates " + MSG("TLS connect error: \"an EOF was observed that violates " "the protocol\"\n"); /* * I presume we took too long on our side and the server grew * impatient. */ } else if (ret == -1) { - MSG("SSL connect error: %s\n", dStrerror(errno)); + MSG("TLS connect error: %s\n", dStrerror(errno)); /* If the following can happen, I'll add code to handle it, but * I don't want to add code blindly if it isn't getting used @@ -956,9 +1076,24 @@ static void Ssl_connect(int fd, int connkey) MSG("SSL_get_error() returned %d on a connect.\n", err1_ret); } } else { - if (Ssl_user_said_yes(conn->url) || - (Ssl_examine_certificate(conn->ssl, conn->url) != -1)) + Server_t *srv = dList_find_sorted(servers, conn->url, + Tls_servers_by_url_cmp); + + if (srv->cert_status == CERT_STATUS_RECEIVING) { + /* Making first connection with the server. Show some information. */ + SSL *ssl = conn->ssl; + const char *version = SSL_get_version(ssl); + const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl); + + MSG("%s: %s, cipher %s\n", URL_AUTHORITY(conn->url), version, + SSL_CIPHER_get_name(cipher)); + Tls_print_cert_chain(ssl); + } + + if (srv->cert_status == CERT_STATUS_USER_ACCEPTED || + (Tls_examine_certificate(conn->ssl, srv, URL_HOST(conn->url))!=-1)) { failed = FALSE; + } } /* @@ -970,7 +1105,7 @@ static void Ssl_connect(int fd, int connkey) if (a_Klist_get_data(conn_list, connkey)) { conn->connecting = FALSE; if (failed) { - Ssl_close_by_key(connkey); + Tls_close_by_key(connkey); } a_IOwatch_remove_fd(fd, DIO_READ|DIO_WRITE); a_Http_connect_done(fd, failed ? FALSE : TRUE); @@ -980,15 +1115,15 @@ static void Ssl_connect(int fd, int connkey) } } -static void Ssl_connect_cb(int fd, void *vconnkey) +static void Tls_connect_cb(int fd, void *vconnkey) { - Ssl_connect(fd, VOIDP2INT(vconnkey)); + Tls_connect(fd, VOIDP2INT(vconnkey)); } /* - * Perform the SSL handshake on an open socket. + * Perform the TLS handshake on an open socket. */ -void a_Ssl_handshake(int fd, const DilloUrl *url) +void a_Tls_handshake(int fd, const DilloUrl *url) { SSL *ssl; bool_t success = TRUE; @@ -997,7 +1132,7 @@ void a_Ssl_handshake(int fd, const DilloUrl *url) if (!ssl_context) success = FALSE; - if (success && Ssl_user_said_no(url)) { + if (success && Tls_user_said_no(url)) { success = FALSE; } @@ -1011,7 +1146,7 @@ void a_Ssl_handshake(int fd, const DilloUrl *url) success = FALSE; } - /* assign SSL connection to this file descriptor */ + /* assign TLS connection to this file descriptor */ if (success && !SSL_set_fd(ssl, fd)) { unsigned long err_ret = ERR_get_error(); do { @@ -1021,7 +1156,7 @@ void a_Ssl_handshake(int fd, const DilloUrl *url) } if (success) - connkey = Ssl_conn_new(fd, url, ssl); + connkey = Tls_conn_new(fd, url, ssl); #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME /* Server Name Indication. From the openssl changelog, it looks like this @@ -1032,42 +1167,42 @@ void a_Ssl_handshake(int fd, const DilloUrl *url) #endif if (!success) { - a_Ssl_reset_server_state(url); + a_Tls_reset_server_state(url); a_Http_connect_done(fd, success); } else { - Ssl_connect(fd, connkey); + Tls_connect(fd, connkey); } } /* - * Read data from an open SSL connection. + * Read data from an open TLS connection. */ -int a_Ssl_read(void *conn, void *buf, size_t len) +int a_Tls_read(void *conn, void *buf, size_t len) { Conn_t *c = (Conn_t*)conn; return SSL_read(c->ssl, buf, len); } /* - * Write data to an open SSL connection. + * Write data to an open TLS connection. */ -int a_Ssl_write(void *conn, void *buf, size_t len) +int a_Tls_write(void *conn, void *buf, size_t len) { Conn_t *c = (Conn_t*)conn; return SSL_write(c->ssl, buf, len); } -void a_Ssl_close_by_fd(int fd) +void a_Tls_close_by_fd(int fd) { FdMapEntry_t *fme = dList_find_custom(fd_map, INT2VOIDP(fd), - Ssl_fd_map_cmp); + Tls_fd_map_cmp); if (fme) { - Ssl_close_by_key(fme->connkey); + Tls_close_by_key(fme->connkey); } } -static void Ssl_servers_freeall() +static void Tls_servers_freeall() { if (servers) { Server_t *s; @@ -1082,7 +1217,7 @@ static void Ssl_servers_freeall() } } -static void Ssl_fd_map_remove_all() +static void Tls_fd_map_remove_all() { if (fd_map) { FdMapEntry_t *fme; @@ -1099,12 +1234,12 @@ static void Ssl_fd_map_remove_all() /* * Clean up the OpenSSL library */ -void a_Ssl_freeall(void) +void a_Tls_freeall(void) { if (ssl_context) SSL_CTX_free(ssl_context); - Ssl_fd_map_remove_all(); - Ssl_servers_freeall(); + Tls_fd_map_remove_all(); + Tls_servers_freeall(); } #endif /* ENABLE_SSL */ diff --git a/src/IO/tls.h b/src/IO/tls.h new file mode 100644 index 00000000..e3892cb2 --- /dev/null +++ b/src/IO/tls.h @@ -0,0 +1,47 @@ +#ifndef __TLS_H__ +#define __TLS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "../url.h" + +#define TLS_CONNECT_NEVER -1 +#define TLS_CONNECT_NOT_YET 0 +#define TLS_CONNECT_READY 1 + +void a_Tls_init(); + + +#ifdef ENABLE_SSL +int a_Tls_connect_ready(const DilloUrl *url); +void a_Tls_reset_server_state(const DilloUrl *url); + +/* Use to initiate a TLS connection. */ +void a_Tls_handshake(int fd, const DilloUrl *url); + +void *a_Tls_connection(int fd); + +void a_Tls_freeall(); + +void a_Tls_close_by_fd(int fd); +int a_Tls_read(void *conn, void *buf, size_t len); +int a_Tls_write(void *conn, void *buf, size_t len); +#else + +#define a_Tls_connect_ready(url) TLS_CONNECT_NEVER +#define a_Tls_reset_server_state(url) ; +#define a_Tls_handshake(fd, url) ; +#define a_Tls_connection(fd) NULL +#define a_Tls_freeall() ; +#define a_Tls_close_by_fd(fd) ; +#define a_Tls_read(conn, buf, len) 0 +#define a_Tls_write(conn, buf, len) 0 +#endif +#ifdef __cplusplus +} +#endif + +#endif /* __TLS_H__ */ + diff --git a/src/cache.c b/src/cache.c index 2cc8c0aa..d8f1a123 100644 --- a/src/cache.c +++ b/src/cache.c @@ -756,6 +756,7 @@ static void Cache_parse_header(CacheEntry_t *entry) if (!web->requester || a_Url_same_organization(entry->Url, web->requester)) { + /* If cookies are third party, don't even consider them. */ char *server_date = Cache_parse_field(header, "Date"); a_Cookies_set(Cookies, entry->Url, server_date); @@ -764,10 +765,6 @@ static void Cache_parse_header(CacheEntry_t *entry) } } } - if (i >= dList_length(ClientQueue)) { - MSG("Cache: cookies not accepted from '%s'\n", URL_STR(entry->Url)); - } - for (i = 0; (data = dList_nth_data(Cookies, i)); ++i) dFree(data); dList_free(Cookies); @@ -857,17 +854,6 @@ static void Cache_finish_msg(CacheEntry_t *entry) MSG("Expected size: %d, Transfer size: %d\n", entry->ExpectedSize, entry->TransferSize); } - if (!entry->TransferSize && !(entry->Flags & CA_Redirect) && - (entry->Flags & WEB_RootUrl)) { - char *eol = strchr(entry->Header->str, '\n'); - if (eol) { - char *status_line = dStrndup(entry->Header->str, - eol - entry->Header->str); - MSG_HTTP("Body of %s was empty. Server sent status: %s\n", - URL_STR_(entry->Url), status_line); - dFree(status_line); - } - } entry->Flags |= CA_GotData; entry->Flags &= ~CA_Stopped; /* it may catch up! */ if (entry->TransferDecoder) { diff --git a/src/dialog.cc b/src/dialog.cc index 10988c98..03949a1c 100644 --- a/src/dialog.cc +++ b/src/dialog.cc @@ -325,6 +325,7 @@ static void choice_cb(Fl_Widget *button, void *number) { choice_answer = VOIDP2INT(number); _MSG("choice_cb: %d\n", choice_answer); + button->window()->hide(); } @@ -358,16 +359,15 @@ int a_Dialog_choice(const char *title, const char *msg, ...) Fl_Window *window = new Fl_Window(ww, wh, title); window->set_modal(); window->begin(); - Fl_Group *ib = new Fl_Group(0, 0, window->w(), window->h()); - ib->begin(); - window->resizable(ib); - if (msg != NULL){ - Fl_Box *box = new Fl_Box(0, 0, ww, wh - bh, msg); - box->labelfont(FL_HELVETICA); - box->labelsize(14); - box->align(FL_ALIGN_WRAP); - } + Fl_Text_Buffer *buf = new Fl_Text_Buffer(); + buf->text(msg); + Fl_Text_Display *td = new Fl_Text_Display(0, 0, ww, wh - bh); + td->buffer(buf); + td->textsize((int) rint(14.0 * prefs.font_factor)); + td->wrap_mode(Fl_Text_Display::WRAP_AT_BOUNDS, 0); + + window->resizable(td); int xpos = gap; va_start(ap, msg); @@ -386,6 +386,8 @@ int a_Dialog_choice(const char *title, const char *msg, ...) while (window->shown()) Fl::wait(); _MSG("Dialog_choice answer = %d\n", answer); + td->buffer(NULL); + delete buf; delete window; return choice_answer; diff --git a/src/dillo.cc b/src/dillo.cc index 847c9d63..17747c59 100644 --- a/src/dillo.cc +++ b/src/dillo.cc @@ -45,7 +45,7 @@ #include "dns.h" #include "web.hh" -#include "IO/ssl.h" +#include "IO/tls.h" #include "IO/Url.h" #include "IO/mime.h" #include "capi.h" @@ -477,7 +477,7 @@ int main(int argc, char **argv) a_Dns_init(); a_Web_init(); a_Http_init(); - a_Ssl_init(); + a_Tls_init(); a_Mime_init(); a_Capi_init(); a_Dicache_init(); @@ -599,7 +599,7 @@ int main(int argc, char **argv) a_Cache_freeall(); a_Dicache_freeall(); a_Http_freeall(); - a_Ssl_freeall(); + a_Tls_freeall(); a_Dns_freeall(); a_History_freeall(); a_Prefs_freeall(); diff --git a/src/html.cc b/src/html.cc index 3e4f27a8..a92771d3 100644 --- a/src/html.cc +++ b/src/html.cc @@ -2514,8 +2514,6 @@ static void if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "href"))) { url = a_Html_url_new(html, attrbuf, NULL, 0); dReturn_if_fail ( url != NULL ); - if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "alt"))) - a_Url_set_alt(url, attrbuf); link = Html_set_new_link(html, &url); } @@ -204,7 +204,6 @@ void a_Url_free(DilloUrl *url) dFree((char *)url->hostname); dFree((char *)url->buffer); dStr_free(url->data, 1); - dFree((char *)url->alt); dFree(url); } } @@ -213,7 +212,6 @@ void a_Url_free(DilloUrl *url) * Resolve the URL as RFC3986 suggests. */ static Dstr *Url_resolve_relative(const char *RelStr, - DilloUrl *BaseUrlPar, const char *BaseStr) { char *p, *s, *e; @@ -224,9 +222,7 @@ static Dstr *Url_resolve_relative(const char *RelStr, /* parse relative URL */ RelUrl = Url_object_new(RelStr); - if (BaseUrlPar) { - BaseUrl = BaseUrlPar; - } else if (RelUrl->scheme == NULL) { + if (RelUrl->scheme == NULL) { /* only required when there's no <scheme> in RelStr */ BaseUrl = Url_object_new(BaseStr); } @@ -336,8 +332,7 @@ static Dstr *Url_resolve_relative(const char *RelStr, done: dStr_free(Path, TRUE); a_Url_free(RelUrl); - if (BaseUrl != BaseUrlPar) - a_Url_free(BaseUrl); + a_Url_free(BaseUrl); return SolvedUrl; } @@ -356,7 +351,6 @@ done: * port = 8080 * flags = URL_Get * data = Dstr * ("") - * alt = NULL * ismap_url_len = 0 * } * @@ -406,7 +400,7 @@ DilloUrl* a_Url_new(const char *url_str, const char *base_url) } /* Resolve the URL */ - SolvedUrl = Url_resolve_relative(urlstr, NULL, base_url); + SolvedUrl = Url_resolve_relative(urlstr, base_url); _MSG("SolvedUrl = %s\n", SolvedUrl->str); /* Fill url data */ @@ -435,7 +429,6 @@ DilloUrl* a_Url_dup(const DilloUrl *ori) url->url_string = dStr_new(URL_STR(ori)); url->port = ori->port; url->flags = ori->flags; - url->alt = dStrdup(ori->alt); url->ismap_url_len = ori->ismap_url_len; url->illegal_chars = ori->illegal_chars; url->illegal_chars_spc = ori->illegal_chars_spc; @@ -495,17 +488,6 @@ void a_Url_set_data(DilloUrl *u, Dstr **data) } /* - * Set DilloUrl alt (alternate text to the URL. Used by image maps) - */ -void a_Url_set_alt(DilloUrl *u, const char *alt) -{ - if (u) { - dFree((char *)u->alt); - u->alt = dStrdup(alt); - } -} - -/* * Set DilloUrl ismap coordinates * (this is optimized for not hogging the CPU) */ @@ -516,7 +498,6 @@ void a_Url_set_ismap_coords(DilloUrl *u, char *coord_str) if (!u->ismap_url_len) { /* Save base-url length (without coords) */ u->ismap_url_len = URL_STR_(u) ? u->url_string->len : 0; - a_Url_set_flags(u, URL_FLAGS(u) | URL_Ismap); } if (u->url_string) { dStr_truncate(u->url_string, u->ismap_url_len); @@ -22,12 +22,8 @@ */ #define URL_Get (1 << 0) #define URL_Post (1 << 1) -#define URL_ISindex (1 << 2) -#define URL_Ismap (1 << 3) -#define URL_RealmAccess (1 << 4) #define URL_E2EQuery (1 << 5) -#define URL_ReloadImages (1 << 6) #define URL_ReloadPage (1 << 7) #define URL_ReloadFromCache (1 << 8) @@ -47,7 +43,6 @@ #define URL_QUERY_(u) (u)->query #define URL_FRAGMENT_(u) (u)->fragment #define URL_HOST_(u) a_Url_hostname(u) -#define URL_ALT_(u) (u)->alt #define URL_STR_(u) a_Url_str(u) /* this returns a Dstr* */ #define URL_DATA_(u) (u)->data @@ -69,9 +64,8 @@ #define URL_QUERY(u) NPTR2STR(URL_QUERY_(u)) #define URL_FRAGMENT(u) NPTR2STR(URL_FRAGMENT_(u)) #define URL_HOST(u) NPTR2STR(URL_HOST_(u)) -#define URL_DATA(u) URL_DATA_(u) -#define URL_ALT(u) NPTR2STR(URL_ALT_(u)) #define URL_STR(u) NPTR2STR(URL_STR_(u)) +#define URL_DATA(u) URL_DATA_(u) #define URL_PORT(u) URL_PORT_(u) #define URL_FLAGS(u) URL_FLAGS_(u) #define URL_ILLEGAL_CHARS(u) URL_ILLEGAL_CHARS_(u) @@ -94,7 +88,6 @@ typedef struct { int port; int flags; Dstr *data; /* POST */ - const char *alt; /* "alt" text (used by image maps) */ int ismap_url_len; /* Used by server side image maps */ int illegal_chars; /* number of illegal chars */ int illegal_chars_spc; /* number of illegal space chars */ @@ -109,7 +102,6 @@ DilloUrl* a_Url_dup(const DilloUrl *u); int a_Url_cmp(const DilloUrl *A, const DilloUrl *B); void a_Url_set_flags(DilloUrl *u, int flags); void a_Url_set_data(DilloUrl *u, Dstr **data); -void a_Url_set_alt(DilloUrl *u, const char *alt); void a_Url_set_ismap_coords(DilloUrl *u, char *coord_str); char *a_Url_decode_hex_str(const char *str); char *a_Url_encode_hex_str(const char *str); |