diff options
-rw-r--r-- | .github/workflows/main.yaml | 4 | ||||
-rw-r--r-- | Makefile.in | 2 | ||||
-rwxr-xr-x | configure | 10 | ||||
-rw-r--r-- | configure.src | 10 | ||||
-rw-r--r-- | erts/emulator/beam/beam_common.c | 6 | ||||
-rw-r--r-- | erts/emulator/beam/jit/x86/instr_bs.cpp | 4 | ||||
-rw-r--r-- | erts/emulator/beam/jit/x86/instr_call.cpp | 8 | ||||
-rw-r--r-- | lib/erl_docgen/priv/css/otp_doc.css | 489 | ||||
-rw-r--r-- | lib/erl_docgen/priv/js/flipmenu/Makefile | 2 | ||||
-rw-r--r-- | lib/erl_docgen/priv/js/topbar.js | 16 | ||||
-rw-r--r-- | lib/erl_docgen/priv/xsl/db_html.xsl | 519 | ||||
-rw-r--r-- | lib/ssl/src/ssl_certificate.erl | 4 | ||||
-rw-r--r-- | lib/ssl/src/ssl_cipher.erl | 154 | ||||
-rw-r--r-- | lib/ssl/src/ssl_handshake.erl | 22 | ||||
-rw-r--r-- | lib/ssl/test/openssl_client_cert_SUITE.erl | 52 | ||||
-rw-r--r-- | lib/ssl/test/ssl_cert_SUITE.erl | 48 | ||||
-rw-r--r-- | lib/ssl/test/ssl_test_lib.erl | 10 | ||||
-rw-r--r-- | make/otp_release_targets.mk | 8 | ||||
-rwxr-xr-x | scripts/otp_html_check | 2 | ||||
-rw-r--r-- | system/doc/top/Makefile | 8 | ||||
-rw-r--r-- | system/doc/top/templates/index.html.src | 54 |
21 files changed, 887 insertions, 545 deletions
diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 0f09ab3d4d..1d1f2b44bc 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -111,6 +111,8 @@ jobs: tar -xzf ./otp_src.tar.gz cd otp export ERL_TOP=`pwd` + export MAKEFLAGS=-j4 + export ERLC_USE_SERVER=true eval `./otp_build env_win32 x64` ./otp_build configure if cat erts/CONF_INFO || cat lib/*/CONF_INFO || cat lib/*/SKIP || cat lib/SKIP-APPLICATIONS; then exit 1; fi @@ -232,8 +234,10 @@ jobs: TAG=${GITHUB_REF#refs/tags/} IS_RELEASE=`$(echo $TAG | grep -E '^OTP-[0-9]+\.[0-9]+$' > /dev/null) \ && echo "true" || echo "false"` + VSN=${TAG#OTP-} echo "::set-output name=tag::${TAG}" echo "::set-output name=release::${IS_RELEASE}" + echo "::set-output name=vsn::${VSN}" - uses: actions/checkout@v2 diff --git a/Makefile.in b/Makefile.in index ab2fc77b06..bf867f66ce 100644 --- a/Makefile.in +++ b/Makefile.in @@ -451,7 +451,7 @@ endif $(DOCGEN)/priv/bin/validate_links.escript $(ERL_TOP) make/$(TARGET)/mod2app.xml \ lib/*/doc/xml/*.xml erts/doc/xml/*.xml system/doc/xml/*/*.xml -mod2app: $(ERL_TOP)/make/$(TARGET)/mod2app.xml +mod2app: doc_bootstrap_build doc_bootstrap_copy $(ERL_TOP)/make/$(TARGET)/mod2app.xml $(ERL_TOP)/make/$(TARGET)/mod2app.xml: erts/doc/src/Makefile lib/*/doc/src/Makefile PATH=$(BOOT_PREFIX)"$${PATH}" escript $(BOOTSTRAP_ROOT)/bootstrap/lib/erl_docgen/priv/bin/xref_mod_app.escript -topdir $(ERL_TOP) -outfile $(ERL_TOP)/make/$(TARGET)/mod2app.xml @@ -55,7 +55,7 @@ skip_applications= while test $# != 0; do case $1 in -srcdir=* | --srcdir=*) - user_srcdir=`expr -- "$1" : '[^=]*=\(.*\)'` + user_srcdir=`echo "$1" | sed 's/^[^=]*=//'` if test "$ERL_TOP" != ""; then echo "WARNING: Overriding ERL_TOP with $user_srcdir" 1>&2 echo "" 1>&2 @@ -95,7 +95,7 @@ while test $# != 0; do echo "" 1>&2 ;; -cache-file=* | --cache-file=* ) - static_cache=`expr -- "$1" : '[^=]*=\(.*\)'` + static_cache=`echo "$1" | sed 's/^[^=]*=//'` if test "$static_cache" != "/dev/null"; then echo "WARNING: Only using config cache file '$static_cache' as static cache" 1>&2 echo "" 1>&2 @@ -140,8 +140,8 @@ while test $# != 0; do pie_ldflags="-no-pie" ;; CFLAGS=* | LDFLAGS=*) - flgs_var=`expr -- "$1" : '\([^=]*\)=.*'` - flgs_val=`expr -- "$1" : '[^=]*=\(.*\)'` + flgs_var=`echo "$1" | sed 's/=.*$//'` + flgs_val=`echo "$1" | sed 's/^[^=]*=//'` eval $flgs_var=\$flgs_val ;; --help=r* | -help=r*) @@ -151,7 +151,7 @@ while test $# != 0; do *) case $1 in --without-*) - skip_app=`expr -- "$1" : '--without-\(.*\)'` + skip_app=`echo "$1" | sed 's/^--without-//'` if [ "$skip_app" = "stdlib" ] || [ "$skip_app" = "kernel" ] || [ "$skip_app" = "sasl" ] || diff --git a/configure.src b/configure.src index 03bc4b3947..f0afd5c6ee 100644 --- a/configure.src +++ b/configure.src @@ -55,7 +55,7 @@ skip_applications= while test $# != 0; do case $1 in -srcdir=* | --srcdir=*) - user_srcdir=`expr -- "$1" : '[^=]*=\(.*\)'` + user_srcdir=`echo "$1" | sed 's/^[^=]*=//'` if test "$ERL_TOP" != ""; then echo "WARNING: Overriding ERL_TOP with $user_srcdir" 1>&2 echo "" 1>&2 @@ -95,7 +95,7 @@ while test $# != 0; do echo "" 1>&2 ;; -cache-file=* | --cache-file=* ) - static_cache=`expr -- "$1" : '[^=]*=\(.*\)'` + static_cache=`echo "$1" | sed 's/^[^=]*=//'` if test "$static_cache" != "/dev/null"; then echo "WARNING: Only using config cache file '$static_cache' as static cache" 1>&2 echo "" 1>&2 @@ -140,8 +140,8 @@ while test $# != 0; do pie_ldflags="-no-pie" ;; CFLAGS=* | LDFLAGS=*) - flgs_var=`expr -- "$1" : '\([^=]*\)=.*'` - flgs_val=`expr -- "$1" : '[^=]*=\(.*\)'` + flgs_var=`echo "$1" | sed 's/=.*$//'` + flgs_val=`echo "$1" | sed 's/^[^=]*=//'` eval $flgs_var=\$flgs_val ;; --help=r* | -help=r*) @@ -151,7 +151,7 @@ while test $# != 0; do *) case $1 in --without-*) - skip_app=`expr -- "$1" : '--without-\(.*\)'` + skip_app=`echo "$1" | sed 's/^--without-//'` if [ "$skip_app" = "stdlib" ] || [ "$skip_app" = "kernel" ] || [ "$skip_app" = "sasl" ] || diff --git a/erts/emulator/beam/beam_common.c b/erts/emulator/beam/beam_common.c index 5eeb9a9807..1a1326450f 100644 --- a/erts/emulator/beam/beam_common.c +++ b/erts/emulator/beam/beam_common.c @@ -1300,11 +1300,7 @@ apply_setup_error_handler(Process* p, Eterm module, Eterm function, Uint arity, * properly adjusted). */ - if (HeapWordsLeft(p) < sz) { - erts_garbage_collect(p, sz, reg, arity); - } - hp = HEAP_TOP(p); - HEAP_TOP(p) += sz; + hp = HAlloc(p, sz); for (i = arity-1; i >= 0; i--) { args = CONS(hp, reg[i], args); hp += 2; diff --git a/erts/emulator/beam/jit/x86/instr_bs.cpp b/erts/emulator/beam/jit/x86/instr_bs.cpp index 7df0b84cae..6e9fc79751 100644 --- a/erts/emulator/beam/jit/x86/instr_bs.cpp +++ b/erts/emulator/beam/jit/x86/instr_bs.cpp @@ -1407,8 +1407,8 @@ void BeamModuleAssembler::emit_bs_add(const ArgVal &Fail, a.and_(RETd, ARG1d); } } - a.and_(RETb, imm(_TAG_PRIMARY_MASK)); - a.cmp(RETb, imm(TAG_PRIMARY_IMMED1)); + a.and_(RETb, imm(_TAG_IMMED1_MASK)); + a.cmp(RETb, imm(_TAG_IMMED1_SMALL)); a.jne(fail); /* Verify that ARG2 >= 0 and multiply ARG2 by the unit. The diff --git a/erts/emulator/beam/jit/x86/instr_call.cpp b/erts/emulator/beam/jit/x86/instr_call.cpp index b79ef5567c..e0ee3543bd 100644 --- a/erts/emulator/beam/jit/x86/instr_call.cpp +++ b/erts/emulator/beam/jit/x86/instr_call.cpp @@ -136,7 +136,7 @@ x86::Mem BeamModuleAssembler::emit_variable_apply(bool includeI) { align_erlang_cp(); a.bind(entry); - emit_enter_runtime<Update::eStack | Update::eHeap>(); + emit_enter_runtime<Update::eReductions | Update::eStack | Update::eHeap>(); a.mov(ARG1, c_p); load_x_reg_array(ARG2); @@ -151,7 +151,7 @@ x86::Mem BeamModuleAssembler::emit_variable_apply(bool includeI) { runtime_call<4>(apply); - emit_leave_runtime<Update::eStack | Update::eHeap>(); + emit_leave_runtime<Update::eReductions | Update::eStack | Update::eHeap>(); a.test(RET, RET); a.short_().jne(dispatch); @@ -185,7 +185,7 @@ x86::Mem BeamModuleAssembler::emit_fixed_apply(const ArgVal &Arity, mov_arg(ARG3, Arity); - emit_enter_runtime<Update::eStack | Update::eHeap>(); + emit_enter_runtime<Update::eReductions | Update::eStack | Update::eHeap>(); a.mov(ARG1, c_p); load_x_reg_array(ARG2); @@ -200,7 +200,7 @@ x86::Mem BeamModuleAssembler::emit_fixed_apply(const ArgVal &Arity, runtime_call<5>(fixed_apply); - emit_leave_runtime<Update::eStack | Update::eHeap>(); + emit_leave_runtime<Update::eReductions | Update::eStack | Update::eHeap>(); a.test(RET, RET); a.short_().jne(dispatch); diff --git a/lib/erl_docgen/priv/css/otp_doc.css b/lib/erl_docgen/priv/css/otp_doc.css index 915782ec8c..7a45a3a4f7 100644 --- a/lib/erl_docgen/priv/css/otp_doc.css +++ b/lib/erl_docgen/priv/css/otp_doc.css @@ -1,24 +1,26 @@ /* standard OTP style sheet */ +/* We use three responsive breakpoints: + * 768px - mobile + * 992px - small screen + * 1200px - medium screen + * default - large screen +*/ body { - background: #fefefe; - color: #1a1a1a; - font-family: sans-serif; - margin: 0; - padding: 0; - border: 0; - overflow: scroll; - height: 100%; - max-height: 100%; - line-height: 1.2em; - font-size: 16px; + background: #fefefe; + color: #1a1a1a; + font-family: sans-serif; + margin: 0; + padding: 0; + border: 0; + max-height: 100%; + line-height: 1.2em; + font-size: 16px; } h1, h2, h3, h4, h5, h6{ - line-height: 1.2em; + line-height: 1.2em; } -p { max-width: 42em } - .header { background: #222; color: #fefefe } .top { background: #efe } .otp { background: #efe } @@ -31,143 +33,310 @@ a:active { color: #1c7cd6; text-decoration: none } a:visited { color: #1b6ec2; text-decoration: none } #container { - width: 100%; - margin: 0; - background-color: #fefefe; + display: grid; + grid-template-columns: 1fr 5fr; + grid-template-areas: "leftnav content"; } #leftnav { - position: fixed; - float: left; - top: 0; - bottom: 0; - left: 0; - width: 300px; - overflow:auto; - margin: 0; - padding: 1px; - border-right: 1px solid #ccc; + grid-area: leftnav; } -.leftnav-tube -{ - margin: 15px; +.leftnav-tube { + top: 0; + margin-left: 15px; + position: sticky; + height: 100vh; + max-width: 250px; + overflow: auto; + border-right: 1px solid #ccc; } #content { - margin-left: 340px; /* set left value to WidthOfFrameDiv */ - max-width: 52em; - overflow-x: hidden; + grid-area: content; + max-width: 52em; + margin-left: 30px; +} + +@media screen and (max-width: 1200px) { + #content { + margin-left: 0px; + } +} + +@media screen and (max-width: 992px) { + #content { + max-width: 35em; + } +} + +.topbar { + grid-area: topbar; + display: none; +} + +@media screen and (max-width: 768px) { + + #container { + grid-template-columns: 100%; + grid-template-areas: + "topbar" + "leftnav" + "content"; + } + + /* styling for the top bar */ + .topbar { + display: flex; + position: relative; + top: 0px; + padding: 0.5em; + width: 100%; + box-sizing: border-box; + border-bottom: 1px solid #ccc; + box-shadow: 0 0.5rem 1rem rgba(0,0,0,0.05), + inset 0 -1px 0 rgba(0,0,0,0.15); + text-align: center; + } + .topbar button { + padding: 1 6 1 6; + margin: 0; + height: auto; + display: inline-block; + border-radius: .25rem; + border: 1px solid transparent; + background: transparent; + } + .topbar-expand:not(.show) > button { + /* When we add the "show" class we rotate the button 180deg */ + transform: rotate(180deg); + } + .topbar-expand > button { + transition: transform 0.35s ease; + } + .topbar-expand.show-permanent > button { + display: none; + } + .topbar-title { + text-align: center; + flex-grow: 2; + } + .topbar-title > h1 { + font-size: 1.17em; + margin: 0px; + } + + /* Break words on mobile */ + #content { + overflow-wrap: break-word; + word-wrap: break-word; + margin-left: 0px; + max-width: 100%; + } + p { + max-width: 100%; + } + /* The h1 is part of the topbar on mobile */ + #content h1 { + display: none; + } + + /* Styling of the navbar when shown/hidden */ + #leftnav { + overflow: hidden; + } + #leftnav:not(.show) { + max-height: 0px; + border-bottom: 0px; + transition: max-height 0.35s ease; + } + #leftnav.show { + max-height: 60vh; + border-bottom: 1px solid #ccc; + box-shadow: 0 0.5rem 1rem rgba(0,0,0,0.05), + inset 0 -1px 0 rgba(0,0,0,0.15); + transition: max-height 0.35s ease; + } + + .leftnav-tube { + max-height: 60vh; + max-width: 100%; + position: unset; + border-right: 0px; + margin-right: 0px; + margin-left: 0px; + padding: 0px 15px 0px 15px; + } + #leftnav.show-permanent { + max-height: none; + } + .show-permanent > .leftnav-tube { + overflow: initial; + max-height: none; + height: inherit; + } + .hide-mobile { + opacity: 0; + } + +} + +@media (prefers-reduced-motion: reduce){ + #leftnav.collapsing{ + transition: none; + } + .topbar-expand > button { + transition: none; + } +} + +.frontpage { + padding-top: 50px; /* Magins for inner DIV inside each DIV (to provide padding) */ +} + +.mobile-only { + display: none; +} + +@media screen and (max-width: 768px) { + .mobile-only { + display: revert; + } +} + +.innertube, .exports-tube { + margin-left: 15px; + margin-right: 15px; +} + +@media screen and (max-width: 1200px) { + .innertube, .exports-tube { + margin-left: 0px; + margin-right: 15px; + } +} + +@media screen and (max-width: 768px) { + .innertube, .exports-tube { + margin-left: 15px; + margin-right: 15px; + } +} + +.footer { + margin: 15px; /* Magins for inner DIV inside each DIV (to provide padding) */ + text-align: center; } -.frontpage -{ - padding-top: 50px; /* Magins for inner DIV inside each DIV (to provide padding) */ -} +.bold_code { font-family: mono, Courier, monospace; font-weight: bold } -.innertube -{ - margin-left: 15px; /* Magins for inner DIV inside each DIV (to provide padding) */ - margin-right: 11em; +.title-link { + display: flex; } -.footer -{ - margin: 15px; /* Magins for inner DIV inside each DIV (to provide padding) */ - text-align: center; +.cref-head, .func-head, .data-type-name { + margin: 0 0 0 -4em; + padding-bottom: 0.2em; + padding-top: 0.2em; } -.bold_code { font-family: mono, Courier, monospace; font-weight: bold } - -/* Invisible table for function specs, - * just to get since-version out in right margin */ -.func-table, .func-tr, .func-td, .cfunc-td, .func-since-td { - width: 100%; - border: 0; - padding: 0; +.cref-head h4, .func-head h4, .data-type-name h4 { margin: 0; } -.func-tr:nth-child(n) { - background: inherit /* turn off zebra striped rows */ -} - -.func-td { - width: 38em; +.cref-head:hover, .func-head:hover, .data-type-name:hover { + background-color: #f5f5f5; } -.cfunc-td { - width: 31em; +/* This small trick is in order to make all but the first line of the function + * head indented by 7em. So that it looks like this: + * int enif_alloc_binary( + * size_t size, + * ErlNifBinary* bin) + */ +.cref-head .title-name { padding-left: 7em; text-indent: -7em; } -.func-since-td { - width: auto; - padding-left: 1em; +.title-since { + margin-left: auto; } -.func-td:hover { - background-color: #f5f5f5; +@media screen and (max-width: 768px) { + .cref-head, .func-head, .data-type-name { + margin-left: 0em; + padding-bottom: 0em; + padding-top: 0em; + } + .title-link { + flex-direction: column; + } + .title-anchors { + display: none; + } + .title-since { + margin-left: 1em; + } } .code { - font-family: mono, Courier, monospace; - font-weight: normal; - background-color: #f3f3f3; + font-family: mono, Courier, monospace; + font-weight: normal; + background-color: #f3f3f3; } .note, .warning, .do, .dont { - border: 1px solid #495057; - margin: 1em 0; + border: 1px solid #495057; + margin: 1em 0; } .note .label { - background-color: #2b8a3e; - color: #fefefe; - font-weight: bold; - padding: 0.5em 1em; + background-color: #2b8a3e; + color: #fefefe; + font-weight: bold; + padding: 0.5em 1em; } .note .content { - background: #f8f9fa; - line-height: 120%; - font-size: 0.9em; - padding: 0.5em 1em; + background: #f8f9fa; + line-height: 120%; + font-size: 0.9em; + padding: 0.5em 1em; } .warning .label { - background: #c92a2a; - color: #fefefe; - font-weight: bold; - padding: 0.5em 1em; + background: #c92a2a; + color: #fefefe; + font-weight: bold; + padding: 0.5em 1em; } .warning .content { - background-color: #f8f9fa; - line-height: 120%; - font-size: 0.9em; - padding: 0.5em 1em; + background-color: #f8f9fa; + line-height: 120%; + font-size: 0.9em; + padding: 0.5em 1em; } .do .label { - background-color: #2b8a3e; - color: #fefefe; - font-weight: bold; - padding: 0.5em 1em; + background-color: #2b8a3e; + color: #fefefe; + font-weight: bold; + padding: 0.5em 1em; } .do .content { - background: #f8f9fa; - line-height: 120%; - font-size: 0.9em; - padding: 0.5em 1em; + background: #f8f9fa; + line-height: 120%; + font-size: 0.9em; + padding: 0.5em 1em; } .dont .label { - background: #c92a2a; - color: #fefefe; - font-weight: bold; - padding: 0.5em 1em; + background: #c92a2a; + color: #fefefe; + font-weight: bold; + padding: 0.5em 1em; } .dont .content { - background-color: #f8f9fa; - line-height: 120%; - font-size: 0.9em; - padding: 0.5em 1em; + background-color: #f8f9fa; + line-height: 120%; + font-size: 0.9em; + padding: 0.5em 1em; } .quote { @@ -175,61 +344,70 @@ a:visited { color: #1b6ec2; text-decoration: none } } .example { - background-color:#f1f3f5; - border: 1px solid #dee2e6; - padding: 0.5em 1em; - margin: 1em 0; - font-size: 0.7em; + background-color:#f1f3f5; + border: 1px solid #dee2e6; + padding: 0.5em 1em; + margin: 1em 0; + font-size: 0.7em; + overflow-x: auto; + max-width: min(100%, 48em); } .extrafrontpageinfo { - color: #C00; - font-weight: bold; - font-size: 1.2em; + color: #C00; + font-weight: bold; + font-size: 1.2em; } pre { - font-family: mono, Courier, monospace; - font-weight: normal; - margin: 0; + font-family: mono, Courier, monospace; + font-weight: normal; + margin: 0; } -.data-types-body, .REFBODY{ - margin-left: 2em; +.data-types-body, .REFBODY { + margin-left: 2em; } .REFTYPES { margin-left: 1.5em } .exports-body { margin-left: 3em; } -.exports-tube -{ - margin-right: 11em; + +@media screen and (max-width: 768px) { + .data-types-body, .REFBODY{ + margin-left: 1em; + } + .REFTYPES { margin-left: 0.75em } + .exports-body { + margin-left: 1em; + } } footer { } .erlang-logo-wrapper{ - text-align: center; - margin-bottom: 1em; + text-align: center; + margin-top: 1em; + margin-bottom: 1em; } .main-title{ - text-align: center; + text-align: center; } .main-description{ - text-align: center; - margin: 2em 0; - font-size: 1.5em; - line-height: 1.5em; + text-align: center; + margin: 2em 0; + font-size: 1.5em; + line-height: 1.5em; } .doc-table-wrapper, .doc-image-wrapper{ - width: 100%; + width: 100%; } .doc-image-wrapper{ - text-align: center; + text-align: center; } .doc-svg { @@ -237,60 +415,60 @@ footer { } } .doc-table, .doc-image{ - min-width: 50%; - margin: 0 auto; - font-size: 0.7em; + min-width: 50%; + margin: 0 auto; + font-size: 0.7em; } .doc-table-caption, .doc-image-caption{ - margin-top: 1em; - font-style: italic; - text-align: center; + margin-top: 1em; + font-style: italic; + text-align: center; } table { - border-collapse: collapse; - min-width: 50%; - margin: 1em; + border-collapse: collapse; + min-width: 50%; + margin: 1em; } table, th, td { - border: 1px solid #666; + border: 1px solid #666; } th, td { - padding: 0.5em; - text-align: left; + padding: 0.5em; + text-align: left; } tr:hover { - background-color: #f5f5f5; + background-color: #f5f5f5; } tr:nth-child(even) { - background-color: #f2f2f2; + background-color: #f2f2f2; } th { - background-color: #777; - color: #fefefe; + background-color: #777; + color: #fefefe; } .section-title, .section-subtitle, .section-version{ - text-align: center; - margin: 0; + text-align: center; + margin: 0; } .section-title{ - font-weight: bold; + font-weight: bold; } .section-version{ - font-size: small; + font-size: small; } .expand-collapse-items{ - font-size: small; + font-size: small; } .title_link { @@ -299,7 +477,6 @@ th { } .ghlink-before { - margin-left: -4em; visibility: hidden; } @@ -340,24 +517,24 @@ th { } hr{ - border: 0; - border-top: 1px solid #aaa; + border: 0; + border-top: 1px solid #aaa; } .section-links, .panel-sections, .expand-collapse-items{ - padding: 0 1em; + padding: 0 1em; } .section-links, .panel-sections{ - margin-top: 0; + margin-top: 0; } a > .code { - color: #1862ab; + color: #1862ab; } .func-types-title{ - font-size: 1em; + font-size: 1em; } .since{ diff --git a/lib/erl_docgen/priv/js/flipmenu/Makefile b/lib/erl_docgen/priv/js/flipmenu/Makefile index be0bed74fb..33cce4e6d6 100644 --- a/lib/erl_docgen/priv/js/flipmenu/Makefile +++ b/lib/erl_docgen/priv/js/flipmenu/Makefile @@ -76,7 +76,7 @@ release_spec: opt release_html_spec: html $(INSTALL_DIR) "$(RELEASE_PATH)/doc/js/flipmenu" $(INSTALL_DATA) $(JS_FILES) $(GIF_FILES) "$(RELEASE_PATH)/doc/js/flipmenu" - $(INSTALL_DATA) ../highlight.js ../highlight.pack.js "$(RELEASE_PATH)/doc/js/" + $(INSTALL_DATA) ../highlight.js ../highlight.pack.js ../topbar.js "$(RELEASE_PATH)/doc/js/" release_docs_spec: $(DOC_TARGETS:%=release_%_spec) diff --git a/lib/erl_docgen/priv/js/topbar.js b/lib/erl_docgen/priv/js/topbar.js new file mode 100644 index 0000000000..ef36f09c8c --- /dev/null +++ b/lib/erl_docgen/priv/js/topbar.js @@ -0,0 +1,16 @@ + +function toggleDisplay() { + var leftnav=document.getElementById('leftnav'); + var topbar=document.getElementsByClassName('topbar-expand')[0]; + if (leftnav.classList.contains('show')) { + leftnav.classList.remove('show'); + topbar.classList.remove('show'); + setTimeout(() => { + leftnav.classList.add('hide-mobile'); + }, 350); + } else { + leftnav.classList.add('show'); + topbar.classList.add('show'); + leftnav.classList.remove('hide-mobile'); + } +} diff --git a/lib/erl_docgen/priv/xsl/db_html.xsl b/lib/erl_docgen/priv/xsl/db_html.xsl index 655d1a61e8..730c5d1447 100644 --- a/lib/erl_docgen/priv/xsl/db_html.xsl +++ b/lib/erl_docgen/priv/xsl/db_html.xsl @@ -229,30 +229,22 @@ <xsl:variable name="curModule" select="ancestor::erlref/module"/> <xsl:variable name="mfas" select="key('mfa', - concat($curModule,':',$name,'/',$arity))"/> - <xsl:choose> - <xsl:when test="generate-id($mfas[1]) != generate-id(.)"> - <!-- Avoid duplicated anchors. See also menu.funcs. --> - </xsl:when> - <xsl:otherwise> - <a name="{$name}-{$arity}"></a> - </xsl:otherwise> - </xsl:choose> + concat($curModule,':',$name,'/',$arity))"/> <!-- Insert an anchor for "anchor" attribute --> <xsl:if test="string-length($anchor) > 0"> - <a name="{$anchor}"></a> + <a name="{$anchor}"></a> </xsl:if> <xsl:variable name="global_types" select="ancestor::erlref/datatypes"/> <xsl:variable name="local_types" select="../type[string-length(@name) > 0]"/> - <xsl:apply-templates select="$spec/contract/clause/head"> - <xsl:with-param name="ghlink" select="ancestor-or-self::*[@ghlink]/@ghlink"/> - <xsl:with-param name="local_types" select="$local_types"/> - <xsl:with-param name="global_types" select="$global_types"/> - <xsl:with-param name="since" select="$since"/> - </xsl:apply-templates> + <xsl:apply-templates select="$spec/contract/clause/head"> + <xsl:with-param name="ghlink" select="ancestor-or-self::*[@ghlink]/@ghlink"/> + <xsl:with-param name="local_types" select="$local_types"/> + <xsl:with-param name="global_types" select="$global_types"/> + <xsl:with-param name="since" select="$since"/> + </xsl:apply-templates> </xsl:when> </xsl:choose> </xsl:template> @@ -264,31 +256,51 @@ <xsl:param name="since"/> <xsl:variable name="mfa" select="concat(concat(../../../name,'-'),../../../arity)"/> <xsl:variable name="id" select="concat(concat($mfa,'-'),generate-id(.))"/> - <table class="func-table"> - <tr class="func-tr"> - <td class="func-td"> - <div class="bold_code func-head" - onMouseOver="document.getElementById('ghlink-{$id}').style.visibility = 'visible';" - onMouseOut="document.getElementById('ghlink-{$id}').style.visibility = 'hidden';"> - <xsl:call-template name="ghlink"> + <h4 id="{$mfa}" class="bold_code title-link func-head" + onMouseOver="document.getElementById('ghlink-{$id}').style.visibility = 'visible';" + onMouseOut="document.getElementById('ghlink-{$id}').style.visibility = 'hidden';"> + <div class="title-anchors"> + <xsl:call-template name="ghlink"> <xsl:with-param name="mfa" select="$mfa"/> <xsl:with-param name="ghlink" select="$ghlink"/> <xsl:with-param name="id" select="$id"/> - </xsl:call-template> - <xsl:apply-templates mode="local_type"> + </xsl:call-template> + </div> + <xsl:variable name="name"> + <xsl:apply-templates mode="local_type"> <xsl:with-param name="local_types" select="$local_types"/> <xsl:with-param name="global_types" select="$global_types"/> - </xsl:apply-templates> - </div> - </td> - <td class="func-since-td"> + </xsl:apply-templates> + </xsl:variable> + <!-- We do not include the erlang: prefix in what is selected by + .title-name. This is so that webcrawlers can select the true + function name, i.e. decode_packet instead of erlang:decode_packet. + --> + <xsl:variable name="head" select="exsl:node-set($name)/text()[1]"/> + <xsl:variable name="tail" select="exsl:node-set($name)/node()[position() > 1]"/> + <xsl:choose> + <xsl:when test="substring($head,1,7) = 'erlang:'"> + <div> + <xsl:text>erlang:</xsl:text> + <span class="title-name"> + <xsl:value-of select="substring-after($head,':')"/> + <xsl:copy-of select="$tail"/> + </span> + </div> + </xsl:when> + <xsl:otherwise> + <span class="title-name"> + <xsl:copy-of select="$name"/> + </span> + </xsl:otherwise> + </xsl:choose> <xsl:if test="string-length($since) > 0"> - <span class="since"><xsl:value-of select="$since"/> - </span> + <div class="title-since"> + <span class="since"><xsl:value-of select="$since"/> + </span> + </div> </xsl:if> - </td> - </tr> - </table> + </h4> </xsl:template> <!-- The *last* <name name="..." arity=".."/> --> @@ -317,7 +329,7 @@ (there is no spec with more than one clause) --> <xsl:if test="count($clause/guard) > 0 or count($type) > 0"> <div class="REFBODY fun-types"> - <h3 class="func-types-title">Types</h3> + <h3 id="types" class="func-types-title">Types</h3> <xsl:choose> <xsl:when test="$output_subtypes"> @@ -479,17 +491,15 @@ <!-- Datatype Title, is the really needed? not used by anything --> <xsl:template match="datatype_title"> <xsl:variable name="title" select="."/> - <h4> - <xsl:call-template name="title_link"> - <xsl:with-param name="title"><xsl:apply-templates/></xsl:with-param> - <xsl:with-param name="link" select="$title"/> - </xsl:call-template> - </h4> + <xsl:call-template name="title_link"> + <xsl:with-param name="title"><xsl:apply-templates/></xsl:with-param> + <xsl:with-param name="link" select="$title"/> + </xsl:call-template> </xsl:template> <!-- Datatype --> <xsl:template match="datatype"> - <div class="data-types-body"> + <article class="data-types-body"> <xsl:choose> <xsl:when test="string-length(name/@name) > 0"> <xsl:variable name="apostrophe">'</xsl:variable> @@ -509,15 +519,19 @@ <xsl:with-param name="by" select="$slash_encoded" /> </xsl:call-template> </xsl:variable> - <div class="data-type-name" + <h4 id="{$id}" class="title-link data-type-name" onMouseOver="document.getElementById('ghlink-{$id}').style.visibility = 'visible';" onMouseOut="document.getElementById('ghlink-{$id}').style.visibility = 'hidden';"> - <xsl:call-template name="ghlink"> - <xsl:with-param name="mfa" select="$id"/> - <xsl:with-param name="id" select="$id"/> - </xsl:call-template> - <xsl:apply-templates select="name"/> - </div> + <div class="title-anchors"> + <xsl:call-template name="ghlink"> + <xsl:with-param name="mfa" select="$id"/> + <xsl:with-param name="id" select="$id"/> + </xsl:call-template> + </div> + <div class="title-name"> + <xsl:apply-templates select="name"/> + </div> + </h4> </xsl:when> <xsl:otherwise> <div class="data-type-name"> @@ -526,7 +540,7 @@ </xsl:otherwise> </xsl:choose> <div class="data-type-desc"><xsl:apply-templates select="desc"/></div> - </div> + </article> </xsl:template> <!-- The "mode" attribute of apply has been used to separate the case @@ -774,6 +788,8 @@ <xsl:param name="curModule"/> <html> <head> + <meta name="viewport" content="width=device-width, initial-scale=1"></meta> + <meta charset="utf-8"></meta> <xsl:choose> <xsl:when test="string-length($stylesheet) > 0"> <link rel="stylesheet" href="{$topdocdir}/{$stylesheet}" type="text/css"/> @@ -792,32 +808,18 @@ </xsl:choose> </head> <body> - <div id="container"> <script id="js" type="text/javascript" language="JavaScript" src="{$topdocdir}/js/flipmenu/flipmenu.js"/> <script id="js2" type="text/javascript" src="{$topdocdir}/js/erlresolvelinks.js"></script> + <script id="js3" type="text/javascript" src="{$topdocdir}/js/topbar.js"></script> <script language="JavaScript" type="text/javascript"> <xsl:text disable-output-escaping="yes"><![CDATA[ <!-- - function getWinHeight() { - var myHeight = 0; - if( typeof( window.innerHeight ) == 'number' ) { - //Non-IE - myHeight = window.innerHeight; - } else if( document.documentElement && ( document.documentElement.clientWidth || - document.documentElement.clientHeight ) ) { - //IE 6+ in 'standards compliant mode' - myHeight = document.documentElement.clientHeight; - } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) { - //IE 4 compatible - myHeight = document.body.clientHeight; - } - return myHeight; - } - function setscrollpos() { - var objf=document.getElementById('loadscrollpos'); - document.getElementById("leftnav").scrollTop = objf.offsetTop - getWinHeight()/2; + var objf = document.getElementById('loadscrollpos'); + if (objf) { + document.getElementById("leftnav").firstChild.scrollTop = objf.offsetTop - 10; + } } function addEvent(obj, evType, fn){ @@ -834,8 +836,41 @@ addEvent(window, 'load', setscrollpos); - //-->]]></xsl:text> + //--> +]]></xsl:text> </script> + <div class="topbar"> + <xsl:variable name="show"> + <xsl:if test="(local-name() = 'application') or (local-name() = 'part') or (local-name() = 'releasenotes')"> + <!-- For index pages we want to always show the navbar for mobile --> + <xsl:text>show show-permanent</xsl:text> + </xsl:if> + </xsl:variable> + <div class="topbar-expand {$show}"> + <button onclick="toggleDisplay();"> + <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 54 54" width="24" height="24"> + <g> + <path style="fill:#000000;" d="M27,54c-0.552,0-1-0.448-1-1V8c0-0.552,0.448-1,1-1s1,0.448,1,1v45C28,53.552,27.552,54,27,54z"/> + <path style="fill:#000000;" d="M11,25c-0.256,0-0.512-0.098-0.707-0.293c-0.391-0.391-0.391-1.023,0-1.414l16-16 + c0.391-0.391,1.023-0.391,1.414,0s0.391,1.023,0,1.414l-16,16C11.512,24.902,11.256,25,11,25z"/> + <path style="fill:#000000;" d="M43,25c-0.256,0-0.512-0.098-0.707-0.293l-16-16c-0.391-0.391-0.391-1.023,0-1.414 + s1.023-0.391,1.414,0l16,16c0.391,0.391,0.391,1.023,0,1.414C43.512,24.902,43.256,25,43,25z"/> + <path style="fill:#000000;" d="M43,2H11c-0.552,0-1-0.448-1-1s0.448-1,1-1h32c0.552,0,1,0.448,1,1S43.552,2,43,2z"/> + </g> + </svg> + </button> + </div> + <div class="topbar-title"> + <h1 id="{header/title}"> + <xsl:if test="string-length($chapnum) > 0"> + <xsl:value-of select="$chapnum"/>  + </xsl:if> + <xsl:value-of select="header/title"/> + </h1> + </div> + <div class="search-expand {$show}"> + </div> + </div> <!-- Generate menu --> <xsl:call-template name="menu"> <xsl:with-param name="chapnum" select="$chapnum"/> @@ -913,10 +948,22 @@ <xsl:template name="menu"> <xsl:param name="chapnum"/> <xsl:param name="curModule"/> + <xsl:variable name="show"> + <xsl:choose> + <xsl:when test="(local-name() = 'application') or (local-name() = 'part') or (local-name() = 'releasenotes')"> + <!-- For index pages we want to always show the navbar for mobile --> + <xsl:text>show show-permanent</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>hide-mobile</xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> <xsl:if test="(local-name() = 'part') or ((local-name() = 'chapter') and ancestor::part)"> <!-- .../part or .../part/chapter --> <xsl:call-template name="menu.ug"> <xsl:with-param name="chapnum" select="$chapnum"/> + <xsl:with-param name="show" select="$show"/> </xsl:call-template> </xsl:if> @@ -930,12 +977,14 @@ <!-- .../internal or .../internal/chapter --> <xsl:call-template name="menu.internal.ug"> <xsl:with-param name="chapnum" select="$chapnum"/> + <xsl:with-param name="show" select="$show"/> </xsl:call-template> </xsl:when> <xsl:when test="(local-name() = 'internal' and descendant::erlref) or (((local-name() = 'erlref') or (local-name() = 'comref') or (local-name() = 'cref') or (local-name() = 'fileref') or (local-name() = 'appref')) and ancestor::internal)"> <!-- .../internal,.../internal/erlref, .../internal/comref or .../internal/cref or .../internal/fileref or .../internal/appref --> <xsl:call-template name="menu.internal.ref"> <xsl:with-param name="curModule" select="$curModule"/> + <xsl:with-param name="show" select="$show"/> </xsl:call-template> </xsl:when> </xsl:choose> @@ -943,12 +992,14 @@ <!-- .../application,.../application/erlref, .../application/comref or .../application/cref or .../application/fileref or .../application/appref --> <xsl:call-template name="menu.ref"> <xsl:with-param name="curModule" select="$curModule"/> + <xsl:with-param name="show" select="$show"/> </xsl:call-template> </xsl:if> <xsl:if test="(local-name() = 'releasenotes') or ((local-name() = 'chapter') and ancestor::releasenotes)"> <!-- releasenotes --> <xsl:call-template name="menu.rn"> <xsl:with-param name="chapnum" select="$chapnum"/> + <xsl:with-param name="show" select="$show"/> </xsl:call-template> </xsl:if> </xsl:template> @@ -981,7 +1032,7 @@ <li><a href="internal_docs.html">Internal Documentation</a></li> </xsl:if> <xsl:if test="boolean(/book/releasenotes)"> - <li><a href="release_notes.html">Release Notes</a></li> + <li><a href="notes.html">Release Notes</a></li> </xsl:if> <xsl:choose> <xsl:when test="string-length($pdfname) > 0"> @@ -1050,17 +1101,16 @@ <!-- Chapter/Section, subsection level 1--> <xsl:template match="chapter/section"> <xsl:param name="chapnum"/> - <h3> - <xsl:for-each select="marker"> - <xsl:call-template name="marker-before-title"/> - </xsl:for-each> - <xsl:call-template name="title_link"> - <xsl:with-param name="title"> - <xsl:value-of select="$chapnum"/>.<xsl:number/>  - <xsl:value-of select="title"/> - </xsl:with-param> - </xsl:call-template> - </h3> + <xsl:for-each select="marker"> + <xsl:call-template name="marker-before-title"/> + </xsl:for-each> + <xsl:call-template name="title_link"> + <xsl:with-param name="title"> + <xsl:value-of select="$chapnum"/>.<xsl:number/>  + <xsl:value-of select="title"/> + </xsl:with-param> + <xsl:with-param name="header" select="'h3'"/> + </xsl:call-template> <xsl:apply-templates> <xsl:with-param name="chapnum" select="$chapnum"/> <xsl:with-param name="sectnum"><xsl:number/></xsl:with-param> @@ -1071,17 +1121,15 @@ <xsl:template match="section/section"> <xsl:param name="chapnum"/> <xsl:param name="sectnum"/> - <h4> - <xsl:for-each select="marker"> - <xsl:call-template name="marker-before-title"/> - </xsl:for-each> - <!-- xsl:value-of select="$partnum"/>.<xsl:value-of select="$chapnum"/>.<xsl:value-of select="$sectnum"/>.<xsl:number/ --> - <xsl:call-template name="title_link"> - <xsl:with-param name="title"> - <xsl:value-of select="title"/> - </xsl:with-param> - </xsl:call-template> - </h4> + <xsl:for-each select="marker"> + <xsl:call-template name="marker-before-title"/> + </xsl:for-each> + <!-- xsl:value-of select="$partnum"/>.<xsl:value-of select="$chapnum"/>.<xsl:value-of select="$sectnum"/>.<xsl:number/ --> + <xsl:call-template name="title_link"> + <xsl:with-param name="title"> + <xsl:value-of select="title"/> + </xsl:with-param> + </xsl:call-template> <xsl:apply-templates> <xsl:with-param name="chapnum" select="$chapnum"/> </xsl:apply-templates> @@ -1106,8 +1154,7 @@ <!-- *ref/Section --> <xsl:template match="erlref/section|cref/section|comref/section|fileref/section|appref/section|funcs/fsdescription"> <xsl:param name="chapnum"/> - <div class="innertube"> - <h3> + <section class="innertube"> <xsl:for-each select="marker"> <xsl:call-template name="marker-before-title"/> </xsl:for-each> @@ -1115,28 +1162,30 @@ <xsl:with-param name="title"> <xsl:value-of select="title"/> </xsl:with-param> + <xsl:with-param name="header" select="'h3'"/> </xsl:call-template> - </h3> - <div class="REFBODY rb-3"> - <xsl:apply-templates> - <xsl:with-param name="chapnum" select="$chapnum"/> - </xsl:apply-templates> - </div> - </div> + <div class="REFBODY rb-3"> + <xsl:apply-templates> + <xsl:with-param name="chapnum" select="$chapnum"/> + </xsl:apply-templates> + </div> + </section> </xsl:template> <!-- *ref/Subsection --> <xsl:template match="erlref/section/section|cref/section/section|comref/section/section|fileref/section/section|appref/section/section"> <xsl:param name="chapnum"/> <xsl:param name="sectnum"/> - <h4> - <xsl:value-of select="title"/> - </h4> - <div class="REFBODY rb-4"> - <xsl:apply-templates> - <xsl:with-param name="chapnum" select="$chapnum"/> - </xsl:apply-templates> - </div> + <section> + <h4 id="{title}"> + <xsl:value-of select="title"/> + </h4> + <div class="REFBODY rb-4"> + <xsl:apply-templates> + <xsl:with-param name="chapnum" select="$chapnum"/> + </xsl:apply-templates> + </div> + </section> </xsl:template> @@ -1445,9 +1494,10 @@ <!-- Menu.internal.chapter --> <xsl:template name="menu.internal.ug"> <xsl:param name="chapnum"/> + <xsl:param name="show"/> - <div id="leftnav"> - <div class="leftnav-tube"> + <aside class="{$show}" id="leftnav"> + <nav class="leftnav-tube"> <xsl:call-template name="erlang_logo"/> @@ -1459,7 +1509,7 @@ <xsl:call-template name="menu_middle"/> - <h3>Chapters</h3> + <h3 id="chapters">Chapters</h3> <ul class="flipMenu" imagepath="{$topdocdir}/js/flipmenu"> <xsl:call-template name="menu.chapter"> @@ -1467,15 +1517,17 @@ <xsl:with-param name="chapnum" select="$chapnum"/> </xsl:call-template> </ul> - </div> - </div> + </nav> + </aside> </xsl:template> <!-- Menu.internal.ref --> <xsl:template name="menu.internal.ref"> <xsl:param name="curModule"/> - <div id="leftnav"> - <div class="leftnav-tube"> + <xsl:param name="show"/> + + <aside class="{$show}" id="leftnav"> + <nav class="leftnav-tube"> <xsl:call-template name="erlang_logo"/> @@ -1487,7 +1539,7 @@ <xsl:call-template name="menu_middle"/> - <h3>Table of Contents</h3> + <h3 id="toc">Table of Contents</h3> <ul class="flipMenu"> <xsl:call-template name="menu.ref2"> @@ -1496,14 +1548,15 @@ <xsl:with-param name="curModule" select="$curModule"/> </xsl:call-template> </ul> - </div> - </div> + </nav> + </aside> </xsl:template> <!-- Menu.internal.chapter combined when we have both modules and free-form chapters --> <xsl:template name="menu.internal.ug_ref"> - <div id="leftnav"> - <div class="leftnav-tube"> + <xsl:param name="show"/> + <aside class="{$show}" id="leftnav"> + <nav class="leftnav-tube"> <xsl:call-template name="erlang_logo"/> <p class="section-title"><xsl:value-of select="/book/header/title"/></p> @@ -1514,7 +1567,7 @@ <xsl:call-template name="menu_middle"/> - <h3>Chapters</h3> + <h3 id="chapters">Chapters</h3> <ul class="flipMenu" imagepath="{$topdocdir}/js/flipmenu"> <xsl:call-template name="menu.chapter"> @@ -1522,7 +1575,7 @@ </xsl:call-template> </ul> - <h3>Modules</h3> + <h3 id="modules">Modules</h3> <ul class="flipMenu"> <xsl:call-template name="menu.ref2"> @@ -1530,8 +1583,8 @@ <!--xsl:with-param name="genFuncMenu" select="true"/--> </xsl:call-template> </ul> - </div> - </div> + </nav> + </aside> </xsl:template> <!--Users Guide --> @@ -1573,9 +1626,10 @@ <!-- Menu.ug --> <xsl:template name="menu.ug"> <xsl:param name="chapnum"/> + <xsl:param name="show"/> - <div id="leftnav"> - <div class="leftnav-tube"> + <aside class="{$show}" id="leftnav"> + <nav class="leftnav-tube"> <xsl:call-template name="erlang_logo"/> @@ -1587,7 +1641,7 @@ <xsl:call-template name="menu_middle"/> - <h3>Chapters</h3> + <h3 id="chapters">Chapters</h3> <ul class="flipMenu" imagepath="{$topdocdir}/js/flipmenu"> <xsl:call-template name="menu.chapter"> @@ -1595,8 +1649,8 @@ <xsl:with-param name="chapnum" select="$chapnum"/> </xsl:call-template> </ul> - </div> - </div> + </nav> + </aside> </xsl:template> @@ -1681,7 +1735,7 @@ <xsl:param name="chapnum"/> <!-- center--> - <h1> + <h1 id="{header/title}"> <xsl:value-of select="$chapnum"/> <xsl:value-of select="header/title"/> </h1> <!-- /center--> @@ -1735,8 +1789,10 @@ <!-- Menu.ref --> <xsl:template name="menu.ref"> <xsl:param name="curModule"/> - <div id="leftnav"> - <div class="leftnav-tube"> + <xsl:param name="show"/> + + <aside class="{$show}" id="leftnav"> + <nav class="leftnav-tube"> <xsl:call-template name="erlang_logo"/> @@ -1748,7 +1804,7 @@ <xsl:call-template name="menu_middle"/> - <h3>Table of Contents</h3> + <h3 id="toc">Table of Contents</h3> <ul class="flipMenu"> <xsl:call-template name="menu.ref2"> @@ -1757,8 +1813,8 @@ <xsl:with-param name="curModule" select="$curModule"/> </xsl:call-template> </ul> - </div> - </div> + </nav> + </aside> </xsl:template> @@ -2266,18 +2322,20 @@ <xsl:template match="description"> <xsl:param name="partnum"/> - <div class="innertube"> - <xsl:call-template name="h3_title_link"> - <xsl:with-param name="title">Description</xsl:with-param> - </xsl:call-template> - <div class="REFBODY description-body"> - <p> - <xsl:apply-templates> - <xsl:with-param name="partnum" select="$partnum"/> - </xsl:apply-templates> - </p> - </div> - </div> + <section class="description"> + <div class="innertube"> + <xsl:call-template name="h3_title_link"> + <xsl:with-param name="title">Description</xsl:with-param> + </xsl:call-template> + <div class="REFBODY description-body"> + <p> + <xsl:apply-templates> + <xsl:with-param name="partnum" select="$partnum"/> + </xsl:apply-templates> + </p> + </div> + </div> + </section> </xsl:template> <!-- Funcs --> @@ -2305,18 +2363,18 @@ <!-- Func --> <xsl:template match="func"> <xsl:param name="partnum"/> - - <xsl:apply-templates select="name"/> - <xsl:apply-templates - select="name[string-length(@arity) > 0 and position()=last()]" - mode="types"/> - - <div class="exports-tube"> - <xsl:apply-templates select="fsummary|type|desc"> - <xsl:with-param name="partnum" select="$partnum"/> - </xsl:apply-templates> - </div> - + <article class="func"> + <xsl:apply-templates select="name"/> + <xsl:apply-templates + select="name[string-length(@arity) > 0 and position()=last()]" + mode="types"/> + + <div class="exports-tube"> + <xsl:apply-templates select="fsummary|type|desc"> + <xsl:with-param name="partnum" select="$partnum"/> + </xsl:apply-templates> + </div> + </article> </xsl:template> <xsl:template match="name"> @@ -2370,23 +2428,13 @@ <xsl:choose> <xsl:when test="ancestor::cref"> - <table class="func-table"> - <tr class="func-tr"> - <td class="cfunc-td"> - <span class="bold_code bc-7"> - <xsl:call-template name="title_link"> - <xsl:with-param name="link" select="substring-before(nametext, '(')"/> - <xsl:with-param name="where" select="'before'"/> - </xsl:call-template> - </span> - </td> - <td class="func-since-td"> - <xsl:if test="string-length(@since) > 0"> - <span class="since"><xsl:value-of select="@since"/></span> - </xsl:if> - </td> - </tr> - </table> + <div class="cref-head bold_code bc-7"> + <xsl:call-template name="title_link"> + <xsl:with-param name="link" select="substring-before(nametext, '(')"/> + <xsl:with-param name="where" select="'before'"/> + <xsl:with-param name="since" select="@since"/> + </xsl:call-template> + </div> </xsl:when> <xsl:when test="ancestor::erlref"> <xsl:variable name="fname"> @@ -2418,26 +2466,16 @@ </div> </xsl:when> <xsl:otherwise> - <table class="func-table"> - <tr class="func-tr"> - <td class="func-td"> - <div class="bold_code fun-type"> - <xsl:call-template name="title_link"> - <xsl:with-param name="link" select="concat(concat($fname,'-'),$arity)"/> - <xsl:with-param name="where" select="'before'"/> - <xsl:with-param name="title"> - <xsl:apply-templates/> - </xsl:with-param> - </xsl:call-template> - </div> - </td> - <td class="func-since-td"> - <xsl:if test="string-length(@since) > 0"> - <span class="since"><xsl:value-of select="@since"/></span> - </xsl:if> - </td> - </tr> - </table> + <div class="bold_code func-head"> + <xsl:call-template name="title_link"> + <xsl:with-param name="link" select="concat(concat($fname,'-'),$arity)"/> + <xsl:with-param name="where" select="'before'"/> + <xsl:with-param name="since" select="@since"/> + <xsl:with-param name="title"> + <xsl:apply-templates/> + </xsl:with-param> + </xsl:call-template> + </div> </xsl:otherwise> </xsl:choose> </xsl:when> @@ -2456,7 +2494,7 @@ <xsl:if test="string-length(@name) = 0 and string-length(@variable) = 0"> <div class="REFBODY rb-5"> - <h3 class="func-types-title">Types</h3> + <h3 id="types" class="func-types-title">Types</h3> <xsl:apply-templates> <xsl:with-param name="partnum" select="$partnum"/> @@ -2492,33 +2530,43 @@ <xsl:template name="h3_title_link"> <xsl:param name="title"/> - <h3> - <xsl:call-template name="title_link"> - <xsl:with-param name="title" select="$title"/> - <xsl:with-param name="link" select="erl:to-link($title)"/> - </xsl:call-template> - </h3> + <xsl:call-template name="title_link"> + <xsl:with-param name="title" select="$title"/> + <xsl:with-param name="link" select="erl:to-link($title)"/> + </xsl:call-template> </xsl:template> <xsl:template name="title_link"> <xsl:param name="title" select="'APPLY'"/> <xsl:param name="link" select="erl:to-link(title)"/> <xsl:param name="where" select="'after'"/> + <xsl:param name="header" select="'h4'"/> + <xsl:param name="since"/> <xsl:param name="ghlink" select="ancestor-or-self::*[@ghlink][position() = 1]/@ghlink"/> <xsl:variable name="id" select="concat(concat($link,'-'), generate-id(.))"/> - <span onMouseOver="document.getElementById('ghlink-{$id}').style.visibility = 'visible';" - onMouseOut="document.getElementById('ghlink-{$id}').style.visibility = 'hidden';"> + + <xsl:element name="{$header}"> + <xsl:attribute name="id"><xsl:value-of select="$link"/></xsl:attribute> + <xsl:attribute name="class">title-link</xsl:attribute> + <xsl:attribute name="onMouseOver"> + <xsl:text>document.getElementById('ghlink-</xsl:text><xsl:value-of select="$id"/><xsl:text>').style.visibility = 'visible';</xsl:text> + </xsl:attribute> + <xsl:attribute name="onMouseOut"> + <xsl:text>document.getElementById('ghlink-</xsl:text><xsl:value-of select="$id"/><xsl:text>').style.visibility = 'hidden';</xsl:text> + </xsl:attribute> <xsl:choose> <xsl:when test="$where = 'before'"> - <xsl:call-template name="ghlink"> - <xsl:with-param name="mfa" select="$link"/> - <xsl:with-param name="id" select="$id"/> - <xsl:with-param name="ghlink" select="$ghlink"/> - <xsl:with-param name="where" select="$where"/> - </xsl:call-template> + <div class="title-anchors"> + <xsl:call-template name="ghlink"> + <xsl:with-param name="mfa" select="$link"/> + <xsl:with-param name="id" select="$id"/> + <xsl:with-param name="ghlink" select="$ghlink"/> + <xsl:with-param name="where" select="$where"/> + </xsl:call-template> + </div> </xsl:when> </xsl:choose> - <a class="title_link" name="{$link}"> + <div class="title-name"> <xsl:choose> <xsl:when test="$title = 'APPLY'"> <xsl:apply-templates/> <!-- like <ret> and <nametext> --> @@ -2527,18 +2575,26 @@ <xsl:copy-of select="$title"/> </xsl:otherwise> </xsl:choose> - </a> + </div> <xsl:choose> <xsl:when test="$where = 'after'"> - <xsl:call-template name="ghlink"> - <xsl:with-param name="mfa" select="$link"/> - <xsl:with-param name="id" select="$id"/> - <xsl:with-param name="ghlink" select="$ghlink"/> - <xsl:with-param name="where" select="$where"/> - </xsl:call-template> + <div class="title-anchors"> + <xsl:call-template name="ghlink"> + <xsl:with-param name="mfa" select="$link"/> + <xsl:with-param name="id" select="$id"/> + <xsl:with-param name="ghlink" select="$ghlink"/> + <xsl:with-param name="where" select="$where"/> + </xsl:call-template> + </div> </xsl:when> </xsl:choose> - </span> + <xsl:if test="string-length($since) > 0"> + <div class="title-since"> + <span class="since"><xsl:value-of select="$since"/> + </span> + </div> + </xsl:if> + </xsl:element> </xsl:template> <xsl:template name="ghlink"> @@ -2566,11 +2622,9 @@ <xsl:template match="desc"> <xsl:param name="partnum"/> <div class="REFBODY rb-7"> - <p> - <xsl:apply-templates> - <xsl:with-param name="partnum" select="$partnum"/> - </xsl:apply-templates> - </p> + <xsl:apply-templates> + <xsl:with-param name="partnum" select="$partnum"/> + </xsl:apply-templates> </div> </xsl:template> @@ -2784,9 +2838,10 @@ <!-- Menu.rn --> <xsl:template name="menu.rn"> <xsl:param name="chapnum"/> + <xsl:param name="show"/> - <div id="leftnav"> - <div class="leftnav-tube"> + <aside class="{$show}" id="leftnav"> + <nav class="leftnav-tube"> <xsl:call-template name="erlang_logo"/> @@ -2798,7 +2853,7 @@ <xsl:call-template name="menu_middle"/> - <h3>Chapters</h3> + <h3 id="chapters">Chapters</h3> <ul class="flipMenu" imagepath="{$topdocdir}/js/flipmenu"> <xsl:call-template name="menu.chapter"> @@ -2806,8 +2861,8 @@ <xsl:with-param name="chapnum" select="$chapnum"/> </xsl:call-template> </ul> - </div> - </div> + </nav> + </aside> </xsl:template> <!-- Special templates to calculate the arity of functions --> diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl index ebaa9a6bec..375a416b95 100644 --- a/lib/ssl/src/ssl_certificate.erl +++ b/lib/ssl/src/ssl_certificate.erl @@ -548,10 +548,10 @@ is_supported_signature_algorithm_1_2(#'OTPCertificate'{signatureAlgorithm = is_supported_signature_algorithm_1_2(#'OTPCertificate'{signatureAlgorithm = SignAlg}, SignAlgs) -> Scheme = ssl_cipher:signature_algorithm_to_scheme(SignAlg), {Hash, Sign, _ } = ssl_cipher:scheme_to_components(Scheme), - lists:member({pre_1_3_hash(Hash), pre_1_3_sign(Sign)}, SignAlgs). + ssl_cipher:is_supported_sign({pre_1_3_hash(Hash), pre_1_3_sign(Sign)}, ssl_cipher:signature_schemes_1_2(SignAlgs)). is_supported_signature_algorithm_1_3(#'OTPCertificate'{signatureAlgorithm = SignAlg}, SignAlgs) -> Scheme = ssl_cipher:signature_algorithm_to_scheme(SignAlg), - lists:member(Scheme, SignAlgs). + ssl_cipher:is_supported_sign(Scheme, SignAlgs). pre_1_3_sign(rsa_pkcs1) -> rsa; diff --git a/lib/ssl/src/ssl_cipher.erl b/lib/ssl/src/ssl_cipher.erl index 35b2da773b..63f46346ee 100644 --- a/lib/ssl/src/ssl_cipher.erl +++ b/lib/ssl/src/ssl_cipher.erl @@ -58,7 +58,9 @@ calc_mac_hash/4, calc_mac_hash/6, is_stream_ciphersuite/1, + is_supported_sign/2, signature_scheme/1, + signature_schemes_1_2/1, scheme_to_components/1, hash_size/1, effective_key_bits/1, @@ -564,6 +566,93 @@ hash_size(sha384) -> hash_size(sha512) -> 64. +is_supported_sign({Hash, rsa} = SignAlgo, HashSigns) -> %% PRE TLS-1.3 + lists:member(SignAlgo, HashSigns) orelse + lists:member({Hash, rsa_pss_rsae}, HashSigns); +is_supported_sign(rsa_pkcs1_sha256 = SignAlgo, HashSigns) -> %% TLS-1.3 leagcy + lists:member(SignAlgo, HashSigns) orelse + lists:member(rsa_pss_rsae_sha256, HashSigns); +is_supported_sign(rsa_pkcs1_sha384 = SignAlgo, HashSigns) -> %% TLS-1.3 leagcy + lists:member(SignAlgo, HashSigns) orelse + lists:member(rsa_pss_rsae_sha384, HashSigns); +is_supported_sign(rsa_pkcs1_sha512 = SignAlgo, HashSigns) -> %% TLS-1.3 leagcy + lists:member(SignAlgo, HashSigns) orelse + lists:member(rsa_pss_rsae_sha512, HashSigns); +is_supported_sign(SignAlgo, HashSigns) -> %% PRE TLS-1.3 SignAlgo::tuple() TLS-1.3 SignAlgo::atom() + lists:member(SignAlgo, HashSigns). + +signature_scheme(rsa_pkcs1_sha256) -> ?RSA_PKCS1_SHA256; +signature_scheme(rsa_pkcs1_sha384) -> ?RSA_PKCS1_SHA384; +signature_scheme(rsa_pkcs1_sha512) -> ?RSA_PKCS1_SHA512; +signature_scheme(ecdsa_secp256r1_sha256) -> ?ECDSA_SECP256R1_SHA256; +signature_scheme(ecdsa_secp384r1_sha384) -> ?ECDSA_SECP384R1_SHA384; +signature_scheme(ecdsa_secp521r1_sha512) -> ?ECDSA_SECP521R1_SHA512; +signature_scheme(rsa_pss_rsae_sha256) -> ?RSA_PSS_RSAE_SHA256; +signature_scheme(rsa_pss_rsae_sha384) -> ?RSA_PSS_RSAE_SHA384; +signature_scheme(rsa_pss_rsae_sha512) -> ?RSA_PSS_RSAE_SHA512; +signature_scheme(eddsa_ed25519) -> ?ED25519; +signature_scheme(eddsa_ed448) -> ?ED448; +signature_scheme(rsa_pss_pss_sha256) -> ?RSA_PSS_PSS_SHA256; +signature_scheme(rsa_pss_pss_sha384) -> ?RSA_PSS_PSS_SHA384; +signature_scheme(rsa_pss_pss_sha512) -> ?RSA_PSS_PSS_SHA512; +signature_scheme(rsa_pkcs1_sha1) -> ?RSA_PKCS1_SHA1; +signature_scheme(ecdsa_sha1) -> ?ECDSA_SHA1; +%% Handling legacy signature algorithms +signature_scheme({Hash0, Sign0}) -> + Hash = hash_algorithm(Hash0), + Sign = sign_algorithm(Sign0), + <<?UINT16(SigAlg)>> = <<?BYTE(Hash),?BYTE(Sign)>>, + SigAlg; +signature_scheme(?RSA_PKCS1_SHA256) -> rsa_pkcs1_sha256; +signature_scheme(?RSA_PKCS1_SHA384) -> rsa_pkcs1_sha384; +signature_scheme(?RSA_PKCS1_SHA512) -> rsa_pkcs1_sha512; +signature_scheme(?ECDSA_SECP256R1_SHA256) -> ecdsa_secp256r1_sha256; +signature_scheme(?ECDSA_SECP384R1_SHA384) -> ecdsa_secp384r1_sha384; +signature_scheme(?ECDSA_SECP521R1_SHA512) -> ecdsa_secp521r1_sha512; +signature_scheme(?RSA_PSS_RSAE_SHA256) -> rsa_pss_rsae_sha256; +signature_scheme(?RSA_PSS_RSAE_SHA384) -> rsa_pss_rsae_sha384; +signature_scheme(?RSA_PSS_RSAE_SHA512) -> rsa_pss_rsae_sha512; +signature_scheme(?ED25519) -> eddsa_ed25519; +signature_scheme(?ED448) -> eddsa_ed448; +signature_scheme(?RSA_PSS_PSS_SHA256) -> rsa_pss_pss_sha256; +signature_scheme(?RSA_PSS_PSS_SHA384) -> rsa_pss_pss_sha384; +signature_scheme(?RSA_PSS_PSS_SHA512) -> rsa_pss_pss_sha512; +signature_scheme(?RSA_PKCS1_SHA1) -> rsa_pkcs1_sha1; +signature_scheme(?ECDSA_SHA1) -> ecdsa_sha1; +%% Handling legacy signature algorithms for logging purposes. These algorithms +%% cannot be used in TLS 1.3 handshakes. +signature_scheme(SignAlgo) when is_integer(SignAlgo) -> + <<?BYTE(Hash),?BYTE(Sign)>> = <<?UINT16(SignAlgo)>>, + {ssl_cipher:hash_algorithm(Hash), ssl_cipher:sign_algorithm(Sign)}; +signature_scheme(_) -> unassigned. + +signature_schemes_1_2(SigAlgs) -> + lists:map(fun(Algs) -> + {Hash, Sign, _} = scheme_to_components(Algs), + {Hash, Sign} + end, SigAlgs). + +%% TODO: reserved code points? + +scheme_to_components(rsa_pkcs1_sha256) -> {sha256, rsa_pkcs1, undefined}; +scheme_to_components(rsa_pkcs1_sha384) -> {sha384, rsa_pkcs1, undefined}; +scheme_to_components(rsa_pkcs1_sha512) -> {sha512, rsa_pkcs1, undefined}; +scheme_to_components(ecdsa_secp256r1_sha256) -> {sha256, ecdsa, secp256r1}; +scheme_to_components(ecdsa_secp384r1_sha384) -> {sha384, ecdsa, secp384r1}; +scheme_to_components(ecdsa_secp521r1_sha512) -> {sha512, ecdsa, secp521r1}; +scheme_to_components(rsa_pss_rsae_sha256) -> {sha256, rsa_pss_rsae, undefined}; +scheme_to_components(rsa_pss_rsae_sha384) -> {sha384, rsa_pss_rsae, undefined}; +scheme_to_components(rsa_pss_rsae_sha512) -> {sha512, rsa_pss_rsae, undefined}; +scheme_to_components(eddsa_ed25519) -> {none, eddsa, ed25519}; +scheme_to_components(eddsa_ed448) -> {none, eddsa, ed448}; +scheme_to_components(rsa_pss_pss_sha256) -> {sha256, rsa_pss_pss, undefined}; +scheme_to_components(rsa_pss_pss_sha384) -> {sha384, rsa_pss_pss, undefined}; +scheme_to_components(rsa_pss_pss_sha512) -> {sha512, rsa_pss_pss, undefined}; +scheme_to_components(rsa_pkcs1_sha1) -> {sha1, rsa_pkcs1, undefined}; +scheme_to_components(ecdsa_sha1) -> {sha1, ecdsa, undefined}; +%% Handling legacy signature algorithms +scheme_to_components({Hash,Sign}) -> {Hash, Sign, undefined}. + %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- @@ -752,71 +841,6 @@ sign_algorithm(Other) when is_integer(Other) andalso ((Other >= 4) and (Other =< sign_algorithm(Other) when is_integer(Other) andalso ((Other >= 224) and (Other =< 255)) -> Other. -signature_scheme(rsa_pkcs1_sha256) -> ?RSA_PKCS1_SHA256; -signature_scheme(rsa_pkcs1_sha384) -> ?RSA_PKCS1_SHA384; -signature_scheme(rsa_pkcs1_sha512) -> ?RSA_PKCS1_SHA512; -signature_scheme(ecdsa_secp256r1_sha256) -> ?ECDSA_SECP256R1_SHA256; -signature_scheme(ecdsa_secp384r1_sha384) -> ?ECDSA_SECP384R1_SHA384; -signature_scheme(ecdsa_secp521r1_sha512) -> ?ECDSA_SECP521R1_SHA512; -signature_scheme(rsa_pss_rsae_sha256) -> ?RSA_PSS_RSAE_SHA256; -signature_scheme(rsa_pss_rsae_sha384) -> ?RSA_PSS_RSAE_SHA384; -signature_scheme(rsa_pss_rsae_sha512) -> ?RSA_PSS_RSAE_SHA512; -signature_scheme(eddsa_ed25519) -> ?ED25519; -signature_scheme(eddsa_ed448) -> ?ED448; -signature_scheme(rsa_pss_pss_sha256) -> ?RSA_PSS_PSS_SHA256; -signature_scheme(rsa_pss_pss_sha384) -> ?RSA_PSS_PSS_SHA384; -signature_scheme(rsa_pss_pss_sha512) -> ?RSA_PSS_PSS_SHA512; -signature_scheme(rsa_pkcs1_sha1) -> ?RSA_PKCS1_SHA1; -signature_scheme(ecdsa_sha1) -> ?ECDSA_SHA1; -%% Handling legacy signature algorithms -signature_scheme({Hash0, Sign0}) -> - Hash = hash_algorithm(Hash0), - Sign = sign_algorithm(Sign0), - <<?UINT16(SigAlg)>> = <<?BYTE(Hash),?BYTE(Sign)>>, - SigAlg; -signature_scheme(?RSA_PKCS1_SHA256) -> rsa_pkcs1_sha256; -signature_scheme(?RSA_PKCS1_SHA384) -> rsa_pkcs1_sha384; -signature_scheme(?RSA_PKCS1_SHA512) -> rsa_pkcs1_sha512; -signature_scheme(?ECDSA_SECP256R1_SHA256) -> ecdsa_secp256r1_sha256; -signature_scheme(?ECDSA_SECP384R1_SHA384) -> ecdsa_secp384r1_sha384; -signature_scheme(?ECDSA_SECP521R1_SHA512) -> ecdsa_secp521r1_sha512; -signature_scheme(?RSA_PSS_RSAE_SHA256) -> rsa_pss_rsae_sha256; -signature_scheme(?RSA_PSS_RSAE_SHA384) -> rsa_pss_rsae_sha384; -signature_scheme(?RSA_PSS_RSAE_SHA512) -> rsa_pss_rsae_sha512; -signature_scheme(?ED25519) -> eddsa_ed25519; -signature_scheme(?ED448) -> eddsa_ed448; -signature_scheme(?RSA_PSS_PSS_SHA256) -> rsa_pss_pss_sha256; -signature_scheme(?RSA_PSS_PSS_SHA384) -> rsa_pss_pss_sha384; -signature_scheme(?RSA_PSS_PSS_SHA512) -> rsa_pss_pss_sha512; -signature_scheme(?RSA_PKCS1_SHA1) -> rsa_pkcs1_sha1; -signature_scheme(?ECDSA_SHA1) -> ecdsa_sha1; -%% Handling legacy signature algorithms for logging purposes. These algorithms -%% cannot be used in TLS 1.3 handshakes. -signature_scheme(SignAlgo) when is_integer(SignAlgo) -> - <<?BYTE(Hash),?BYTE(Sign)>> = <<?UINT16(SignAlgo)>>, - {ssl_cipher:hash_algorithm(Hash), ssl_cipher:sign_algorithm(Sign)}; -signature_scheme(_) -> unassigned. -%% TODO: reserved code points? - -scheme_to_components(rsa_pkcs1_sha256) -> {sha256, rsa_pkcs1, undefined}; -scheme_to_components(rsa_pkcs1_sha384) -> {sha384, rsa_pkcs1, undefined}; -scheme_to_components(rsa_pkcs1_sha512) -> {sha512, rsa_pkcs1, undefined}; -scheme_to_components(ecdsa_secp256r1_sha256) -> {sha256, ecdsa, secp256r1}; -scheme_to_components(ecdsa_secp384r1_sha384) -> {sha384, ecdsa, secp384r1}; -scheme_to_components(ecdsa_secp521r1_sha512) -> {sha512, ecdsa, secp521r1}; -scheme_to_components(rsa_pss_rsae_sha256) -> {sha256, rsa_pss_rsae, undefined}; -scheme_to_components(rsa_pss_rsae_sha384) -> {sha384, rsa_pss_rsae, undefined}; -scheme_to_components(rsa_pss_rsae_sha512) -> {sha512, rsa_pss_rsae, undefined}; -scheme_to_components(eddsa_ed25519) -> {none, eddsa, ed25519}; -scheme_to_components(eddsa_ed448) -> {none, eddsa, ed448}; -scheme_to_components(rsa_pss_pss_sha256) -> {sha256, rsa_pss_pss, undefined}; -scheme_to_components(rsa_pss_pss_sha384) -> {sha384, rsa_pss_pss, undefined}; -scheme_to_components(rsa_pss_pss_sha512) -> {sha512, rsa_pss_pss, undefined}; -scheme_to_components(rsa_pkcs1_sha1) -> {sha1, rsa_pkcs1, undefined}; -scheme_to_components(ecdsa_sha1) -> {sha1, ecdsa, undefined}; -%% Handling legacy signature algorithms -scheme_to_components({Hash,Sign}) -> {Hash, Sign, undefined}. - signature_algorithm_to_scheme(#'SignatureAlgorithm'{algorithm = ?'id-RSASSA-PSS', parameters = #'RSASSA-PSS-params'{ maskGenAlgorithm = diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index 63fbf5ffff..e7bbea3591 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -997,8 +997,15 @@ available_signature_algs(_, _) -> available_signature_algs(undefined, SupportedHashSigns, _, Version) when Version >= {3,3} -> SupportedHashSigns; -available_signature_algs(#hash_sign_algos{hash_sign_algos = ClientHashSigns}, SupportedHashSigns, +available_signature_algs(#hash_sign_algos{hash_sign_algos = ClientHashSigns}, SupportedHashSigns0, _, Version) when Version >= {3,3} -> + SupportedHashSigns = + case (Version == {3,3}) andalso contains_scheme(SupportedHashSigns0) of + true -> + ssl_cipher:signature_schemes_1_2(SupportedHashSigns0); + false -> + SupportedHashSigns0 + end, sets:to_list(sets:intersection(sets:from_list(ClientHashSigns), sets:from_list(SupportedHashSigns))); available_signature_algs(_, _, _, _) -> @@ -3278,6 +3285,15 @@ filter_hashsigns([Suite | Suites], [#{key_exchange := KeyExchange} | Algos], Has %% In this case hashsigns is not used as the kexchange is anonaymous filter_hashsigns(Suites, Algos, HashSigns, Version, [Suite| Acc]). +do_filter_hashsigns(rsa = SignAlgo, Suite, Suites, Algos, HashSigns, {3,3} = Version, Acc) -> + case (lists:keymember(SignAlgo, 2, HashSigns) orelse + lists:keymember(rsa_pss_rsae, 2, HashSigns) orelse + lists:keymember(rsa_pss_pss, 2, HashSigns)) of + true -> + filter_hashsigns(Suites, Algos, HashSigns, Version, [Suite| Acc]); + false -> + filter_hashsigns(Suites, Algos, HashSigns, Version, Acc) + end; do_filter_hashsigns(SignAlgo, Suite, Suites, Algos, HashSigns, Version, Acc) -> case lists:keymember(SignAlgo, 2, HashSigns) of true -> @@ -3390,8 +3406,7 @@ is_acceptable_cert_type(Sign, Types) -> %% signature_algorithms_cert = undefined is_supported_sign(SignAlgo, _, HashSigns, []) -> - lists:member(SignAlgo, HashSigns); - + ssl_cipher:is_supported_sign(SignAlgo, HashSigns); %% {'SignatureAlgorithm',{1,2,840,113549,1,1,11},'NULL'} is_supported_sign({Hash, Sign}, 'NULL', _, SignatureSchemes) -> Fun = fun (Scheme, Acc) -> @@ -3408,7 +3423,6 @@ is_supported_sign({Hash, Sign}, 'NULL', _, SignatureSchemes) -> Hash =:= H1) end, lists:foldl(Fun, false, SignatureSchemes); - %% TODO: Implement validation for the curve used in the signature %% RFC 3279 - 2.2.3 ECDSA Signature Algorithm %% When the ecdsa-with-SHA1 algorithm identifier appears as the diff --git a/lib/ssl/test/openssl_client_cert_SUITE.erl b/lib/ssl/test/openssl_client_cert_SUITE.erl index ad00f2da1f..c78bd9eadc 100644 --- a/lib/ssl/test/openssl_client_cert_SUITE.erl +++ b/lib/ssl/test/openssl_client_cert_SUITE.erl @@ -82,7 +82,7 @@ groups() -> [ {openssl_client, [], protocol_groups()}, {'tlsv1.3', [], tls_1_3_protocol_groups()}, - {'tlsv1.2', [], pre_tls_1_3_protocol_groups()}, + {'tlsv1.2', [], pre_tls_1_3_protocol_groups()}, %% Seems to be broken in OpenSSL [{group, rsa_pss_rsae}, {group, rsa_pss_pss}]}, {'tlsv1.1', [], pre_tls_1_3_protocol_groups()}, {'tlsv1', [], pre_tls_1_3_protocol_groups()}, {'dtlsv1.2', [], pre_tls_1_3_protocol_groups()}, @@ -92,8 +92,10 @@ groups() -> {dsa, [], all_version_tests()}, {rsa_1_3, [], all_version_tests() ++ tls_1_3_tests() ++ [unsupported_sign_algo_client_auth, unsupported_sign_algo_cert_client_auth]}, - {rsa_pss_rsae, [], all_version_tests() ++ tls_1_3_tests()}, + {rsa_pss_rsae, [], all_version_tests()}, {rsa_pss_pss, [], all_version_tests() ++ tls_1_3_tests()}, + {rsa_pss_rsae_1_3, [], all_version_tests() ++ tls_1_3_tests()}, + {rsa_pss_pss_1_3, [], all_version_tests() ++ tls_1_3_tests()}, {ecdsa_1_3, [], all_version_tests() ++ tls_1_3_tests()}, {eddsa_1_3, [], all_version_tests() ++ tls_1_3_tests()} ]. @@ -122,8 +124,8 @@ pre_tls_1_3_protocol_groups() -> tls_1_3_protocol_groups() -> [{group, rsa_1_3}, - {group, rsa_pss_rsae}, - {group, rsa_pss_pss}, + {group, rsa_pss_rsae_1_3}, + {group, rsa_pss_pss_1_3}, {group, ecdsa_1_3}, {group, eddsa_1_3} ]. @@ -198,23 +200,26 @@ init_per_group(Group, Config0) when Group == rsa; [] -> {skip, {no_sup, Group, Version}} end; -init_per_group(Alg, Config) when Alg == rsa_pss_rsae; - Alg == rsa_pss_pss -> +init_per_group(Alg, Config) when + Alg == rsa_pss_rsae; + Alg == rsa_pss_pss; + Alg == rsa_pss_rsae_1_3; + Alg == rsa_pss_pss_1_3 -> Supports = crypto:supports(), RSAOpts = proplists:get_value(rsa_opts, Supports), case lists:member(rsa_pkcs1_pss_padding, RSAOpts) andalso lists:member(rsa_pss_saltlen, RSAOpts) andalso lists:member(rsa_mgf1_md, RSAOpts) - andalso ssl_test_lib:is_sane_oppenssl_pss(Alg) + andalso ssl_test_lib:is_sane_oppenssl_pss(rsa_alg(Alg)) of true -> #{client_config := COpts, - server_config := SOpts} = ssl_test_lib:make_rsa_pss_pem(Alg, [], Config, ""), - [{cert_key_alg, Alg} | + server_config := SOpts} = ssl_test_lib:make_rsa_pss_pem(rsa_alg(Alg), [], Config, ""), + [{cert_key_alg, rsa_alg(Alg)} | lists:delete(cert_key_alg, - [{client_cert_opts, COpts}, - {server_cert_opts, SOpts} | + [{client_cert_opts, openssl_sig_algs(Alg) ++ COpts}, + {server_cert_opts, sig_algs(rsa_alg(Alg)) ++ SOpts} | lists:delete(server_cert_opts, lists:delete(client_cert_opts, Config))])]; false -> @@ -433,3 +438,28 @@ hello_retry_client_auth_empty_cert_rejected() -> ssl_cert_tests:hello_retry_client_auth_empty_cert_rejected(). hello_retry_client_auth_empty_cert_rejected(Config) -> ssl_cert_tests:hello_retry_client_auth_empty_cert_rejected(Config). + +rsa_alg(rsa_pss_rsae_1_3) -> + rsa_pss_rsae; +rsa_alg(rsa_pss_pss_1_3) -> + rsa_pss_pss; +rsa_alg(Atom) -> + Atom. + +sig_algs(rsa_pss_pss) -> + [{signature_algs, [rsa_pss_pss_sha512, + rsa_pss_pss_sha384, + rsa_pss_pss_sha256]}]; +sig_algs(rsa_pss_rsae) -> + [{signature_algs,[rsa_pss_rsae_sha512, + rsa_pss_rsae_sha384, + rsa_pss_rsae_sha256]}]. + +openssl_sig_algs(rsa_pss_pss) -> + [{sigalgs, "rsa_pss_pss_sha256"}]; +openssl_sig_algs(rsa_pss_rsae) -> + [{sigalgs,"rsa_pss_rsae_sha256"}]; +openssl_sig_algs(rsa_pss_pss_1_3) -> + [{sigalgs, "rsa_pss_rsae_sha512:rsa_pss_rsae_sha384:rsa_pss_pss_sha256"}]; +openssl_sig_algs(rsa_pss_rsae_1_3) -> + [{sigalgs,"rsa_pss_rsae_sha512:rsa_pss_rsae_sha384:rsa_pss_rsae_sha256"}]. diff --git a/lib/ssl/test/ssl_cert_SUITE.erl b/lib/ssl/test/ssl_cert_SUITE.erl index 42c44e4855..1eef4a48be 100644 --- a/lib/ssl/test/ssl_cert_SUITE.erl +++ b/lib/ssl/test/ssl_cert_SUITE.erl @@ -146,11 +146,11 @@ groups() -> {'tlsv1', [], ssl_protocol_groups()}, {'dtlsv1.2', [], tls_1_2_protocol_groups()}, {'dtlsv1', [], ssl_protocol_groups()}, - {rsa, [], all_version_tests() ++ rsa_tests() ++ pre_tls_1_3_rsa_tests()}, + {rsa, [], all_version_tests() ++ rsa_tests() ++ pre_tls_1_3_rsa_tests() ++ [client_auth_seelfsigned_peer]}, {ecdsa, [], all_version_tests()}, {dsa, [], all_version_tests()}, {rsa_1_3, [], all_version_tests() ++ rsa_tests() ++ - tls_1_3_tests() ++ tls_1_3_rsa_tests() ++ [basic_rsa_1024]}, + tls_1_3_tests() ++ tls_1_3_rsa_tests() ++ [client_auth_seelfsigned_peer, basic_rsa_1024]}, {rsa_pss_rsae, [], all_version_tests() ++ tls_1_2_rsa_tests()}, {rsa_pss_rsae_1_3, [], all_version_tests() ++ rsa_tests() ++ tls_1_3_tests() ++ tls_1_3_rsa_tests()}, {rsa_pss_pss, [], all_version_tests()}, @@ -226,7 +226,6 @@ all_version_tests() -> client_auth_do_not_allow_partial_chain, client_auth_partial_chain_fun_fail, client_auth_sni, - client_auth_seelfsigned_peer, missing_root_cert_no_auth, missing_root_cert_auth, missing_root_cert_auth_user_verify_fun_accept, @@ -296,37 +295,9 @@ do_init_per_group(Alg, Config) when Alg == rsa_pss_rsae; true -> #{client_config := COpts, server_config := SOpts} = ssl_test_lib:make_rsa_pss_pem(rsa_alg(Alg), [], Config, ""), - [{cert_key_alg, rsa_alg(Alg)}, - {extra_client, [{signature_algs, [rsa_pss_pss_sha512, - rsa_pss_pss_sha384, - rsa_pss_pss_sha256, - rsa_pss_rsae_sha512, - rsa_pss_rsae_sha384, - rsa_pss_rsae_sha256, - rsa_pkcs1_sha512, - rsa_pkcs1_sha384, - rsa_pkcs1_sha256, - rsa_pkcs1_sha1, - {sha512, rsa}, - {sha384, rsa}, - {sha256, rsa}, - {sha224, rsa} - ]}]}, - {extra_server, [{signature_algs, [rsa_pss_pss_sha512, - rsa_pss_pss_sha384, - rsa_pss_pss_sha256, - rsa_pss_rsae_sha512, - rsa_pss_rsae_sha384, - rsa_pss_rsae_sha256, - {sha512, ecdsa}, - {sha512, rsa}, - {sha384, ecdsa}, - {sha384, rsa}, - {sha256, ecdsa}, - {sha256, rsa}, - {sha224, ecdsa}, - {sha224, rsa} - ]}]} | + [{cert_key_alg, Alg}, + {extra_client, sig_algs(Alg)}, + {extra_server, sig_algs(Alg)} | lists:delete(cert_key_alg, [{client_cert_opts, COpts}, {server_cert_opts, SOpts} | @@ -1317,3 +1288,12 @@ chain_and_root(Config) -> {ok, ExtractedCAs} = ssl_pkix_db:extract_trusted_certs({der, proplists:get_value(cacerts, Config)}), {ok, Root, Chain} = ssl_certificate:certificate_chain(OwnCert, ets:new(foo, []), ExtractedCAs, [], encoded), {Chain, Root}. + +sig_algs(rsa_pss_pss) -> + [{signature_algs, [rsa_pss_pss_sha512, + rsa_pss_pss_sha384, + rsa_pss_pss_sha256]}]; +sig_algs(rsa_pss_rsae) -> + [{signature_algs, [rsa_pss_rsae_sha512, + rsa_pss_rsae_sha384, + rsa_pss_rsae_sha256]}]. diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index e4c23c22cf..183899e5f2 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -2080,6 +2080,7 @@ start_client(openssl, Port, ClientOpts, Config) -> Ciphers = proplists:get_value(ciphers, ClientOpts, ssl:cipher_suites(default,Version)), Groups0 = proplists:get_value(groups, ClientOpts), CertArgs = openssl_cert_options(ClientOpts, client), + SigAlgs = openssl_sigalgs(proplists:get_value(sigalgs, ClientOpts, undefined)), AlpnArgs = openssl_alpn_options(proplists:get_value(alpn, ClientOpts, undefined)), NpnArgs = openssl_npn_options(proplists:get_value(np, ClientOpts, undefined)), Reconnect = openssl_reconect_option(proplists:get_value(reconnect, ClientOpts, false)), @@ -2096,7 +2097,7 @@ start_client(openssl, Port, ClientOpts, Config) -> "-connect", hostname_format(HostName) ++ ":" ++ integer_to_list(Port), cipher_flag(Version), ciphers(Ciphers, Version), version_flag(Version)] - ++ CertArgs ++ AlpnArgs ++ NpnArgs ++ Reconnect ++ MaxFragLen ++ SessionArgs + ++ CertArgs ++ SigAlgs ++ AlpnArgs ++ NpnArgs ++ Reconnect ++ MaxFragLen ++ SessionArgs ++ Debug; Group -> ["s_client", @@ -2104,7 +2105,7 @@ start_client(openssl, Port, ClientOpts, Config) -> "-connect", hostname_format(HostName) ++ ":" ++ integer_to_list(Port), cipher_flag(Version), ciphers(Ciphers, Version), "-groups", Group, version_flag(Version)] - ++ CertArgs ++ AlpnArgs ++ NpnArgs ++ Reconnect ++ MaxFragLen ++ SessionArgs + ++ CertArgs ++ SigAlgs ++ AlpnArgs ++ NpnArgs ++ Reconnect ++ MaxFragLen ++ SessionArgs ++ Debug end, Args = maybe_force_ipv4(Args0), @@ -2347,6 +2348,11 @@ cert_option("-cert_chain", Value) -> cert_option(Opt, Value) -> [Opt, Value]. +openssl_sigalgs(undefined) -> + []; +openssl_sigalgs(SigAlgs) -> + ["-sigalgs", SigAlgs]. + supported_eccs(Opts) -> ToCheck = proplists:get_value(eccs, Opts, []), Supported = ssl:eccs(), diff --git a/make/otp_release_targets.mk b/make/otp_release_targets.mk index a2ba51c9cf..f525368d7a 100644 --- a/make/otp_release_targets.mk +++ b/make/otp_release_targets.mk @@ -187,11 +187,15 @@ local_docs: local_copy_of_topdefs docs local_html: TOPDOCDIR=. local_html: local_copy_of_topdefs html -local_copy_of_topdefs: - $(INSTALL) $(DOCGEN)/priv/css/otp_doc.css $(HTMLDIR) +$(HTMLDIR)/otp_doc.css: + ln -s $(DOCGEN)/priv/css/otp_doc.css $(HTMLDIR)/otp_doc.css + +local_copy_of_topdefs: $(HTMLDIR)/otp_doc.css + cd $(ERL_TOP) && make mod2app $(INSTALL) $(DOCGEN)/priv/images/erlang-logo.png $(HTMLDIR) $(INSTALL) $(DOCGEN)/priv/images/erlang-logo.gif $(HTMLDIR) $(INSTALL_DIR) $(HTMLDIR)/js/flipmenu + $(INSTALL) $(DOCGEN)/priv/js/*.js $(HTMLDIR)/js $(INSTALL) $(DOCGEN)/priv/js/flipmenu/flip_closed.gif \ $(DOCGEN)/priv/js/flipmenu/flip_open.gif \ $(DOCGEN)/priv/js/flipmenu/flip_static.gif \ diff --git a/scripts/otp_html_check b/scripts/otp_html_check index 893d2b55f1..3606ed22d4 100755 --- a/scripts/otp_html_check +++ b/scripts/otp_html_check @@ -226,7 +226,7 @@ sub get_page_links { ($html =~ m/ < \s* - A + (?: A|H[1-6]) [^>]* \s (?: NAME|ID) \s* = \s* (?: \"([^\"]*)\" | \'([^\']*)\' | ([^>\s]+) ) diff --git a/system/doc/top/Makefile b/system/doc/top/Makefile index 3ebee96c08..803f907994 100644 --- a/system/doc/top/Makefile +++ b/system/doc/top/Makefile @@ -260,9 +260,9 @@ $(TOP_PDF_FILE): $(XML_FILES) pdf: $(TOP_PDF_FILE) -html: $(INDEX_FILES) $(JAVASCRIPT) +html: $(INDEX_FILES) $(JAVASCRIPT) $(MAN_INDEX) -man: $(MAN_INDEX) +man: debug opt: @@ -287,10 +287,10 @@ $(RELSYSDIR)/docbuild: $(INSTALL_DIR) $(RELSYSDIR)/docbuild release_man_spec: man $(RELSYSDIR)/docbuild - $(INSTALL_DATA) $(MAN_INDEX) $(RELSYSDIR) - $(INSTALL_DATA) $(MAN_INDEX_SRC) $(MAN_INDEX_SCRIPT) $(RELSYSDIR)/docbuild release_html_spec: html $(RELSYSDIR)/docbuild + $(INSTALL_DATA) $(MAN_INDEX) $(RELSYSDIR) + $(INSTALL_DATA) $(MAN_INDEX_SRC) $(MAN_INDEX_SCRIPT) $(RELSYSDIR)/docbuild $(INSTALL_DIR) $(RELSYSDIR)/js $(INSTALL_DATA) $(JAVASCRIPT) $(RELSYSDIR)/js $(INSTALL_DATA) $(INDEX_FILES) $(RELSYSDIR) diff --git a/system/doc/top/templates/index.html.src b/system/doc/top/templates/index.html.src index ec53a5b3c5..0c899efe0c 100644 --- a/system/doc/top/templates/index.html.src +++ b/system/doc/top/templates/index.html.src @@ -20,20 +20,45 @@ limitations under the License. --> <html> -<head> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1"></meta> + <meta charset="utf-8"></meta> <link rel="stylesheet" href="otp_doc.css" type="text/css"/> <title>Erlang/OTP #otp_base_vsn#</title> <script id="js" type="text/javascript" language="JavaScript" src="js/flipmenu/flipmenu.js"> - +</script> +<script id="js2" type="text/javascript" language="JavaScript" src="js/topbar.js"> </script> </head> <body> - -<div id="container"> -<div id="leftnav"> -<div class="leftnav-tube"> + <div id="container"> + <div class="topbar"> + <div class="topbar-expand"> + <button onclick="toggleDisplay();"> + <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 54 54" width="24" height="24"> +<g> + <path style="fill:#000000;" d="M27,54c-0.552,0-1-0.448-1-1V8c0-0.552,0.448-1,1-1s1,0.448,1,1v45C28,53.552,27.552,54,27,54z"/> + <path style="fill:#000000;" d="M11,25c-0.256,0-0.512-0.098-0.707-0.293c-0.391-0.391-0.391-1.023,0-1.414l16-16 + c0.391-0.391,1.023-0.391,1.414,0s0.391,1.023,0,1.414l-16,16C11.512,24.902,11.256,25,11,25z"/> + <path style="fill:#000000;" d="M43,25c-0.256,0-0.512-0.098-0.707-0.293l-16-16c-0.391-0.391-0.391-1.023,0-1.414 + s1.023-0.391,1.414,0l16,16c0.391,0.391,0.391,1.023,0,1.414C43.512,24.902,43.256,25,43,25z"/> + <path style="fill:#000000;" d="M43,2H11c-0.552,0-1-0.448-1-1s0.448-1,1-1h32c0.552,0,1,0.448,1,1S43.552,2,43,2z"/> +</g> + </svg> + </button> + </div> + <div class="topbar-title"> + <h1> + Erlang/OTP #otp_base_vsn# + </h1> + </div> + <div class="search-expand"> + </div> + </div> +<aside id="leftnav"> +<nav class="leftnav-tube"> <div class="erlang-logo-wrapper"> <img alt="Erlang logo" src="erlang-logo.png" class="erlang-logo"/ > </div> @@ -78,8 +103,8 @@ limitations under the License. #applinks# </ul> -</div> -</div> +</nav> +</aside> <div id="content"> @@ -92,7 +117,18 @@ limitations under the License. <h2>Some hints that may get you started faster</h2> <ul> - + <li class="mobile-only"> + The navigation menu can be accessed by clicking the <svg style="transform: rotate(180deg);" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 54 54" width="24" height="24"> +<g> + <path style="fill:#000000;" d="M27,54c-0.552,0-1-0.448-1-1V8c0-0.552,0.448-1,1-1s1,0.448,1,1v45C28,53.552,27.552,54,27,54z"/> + <path style="fill:#000000;" d="M11,25c-0.256,0-0.512-0.098-0.707-0.293c-0.391-0.391-0.391-1.023,0-1.414l16-16 + c0.391-0.391,1.023-0.391,1.414,0s0.391,1.023,0,1.414l-16,16C11.512,24.902,11.256,25,11,25z"/> + <path style="fill:#000000;" d="M43,25c-0.256,0-0.512-0.098-0.707-0.293l-16-16c-0.391-0.391-0.391-1.023,0-1.414 + s1.023-0.391,1.414,0l16,16c0.391,0.391,0.391,1.023,0,1.414C43.512,24.902,43.256,25,43,25z"/> + <path style="fill:#000000;" d="M43,2H11c-0.552,0-1-0.448-1-1s0.448-1,1-1h32c0.552,0,1,0.448,1,1S43.552,2,43,2z"/> +</g> + </svg> symbol in the top left corner. + </li> <li> The Erlang language is described in the <a href="reference_manual/users_guide.html">Erlang Reference Manual</a>. |