From 6940bf78a6d2dd6080f8d7f720eb66c17d1a11db Mon Sep 17 00:00:00 2001 From: =?utf8?q?Paul=20H=C3=A4nsch?= Date: Thu, 5 Jul 2018 14:40:11 +0200 Subject: [PATCH 01/16] path cononicalization function (works on non-exist pathes unlike realpath) --- cgilite.sh | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/cgilite.sh b/cgilite.sh index f227d27..13cdb3c 100755 --- a/cgilite.sh +++ b/cgilite.sh @@ -50,7 +50,7 @@ HEX_DECODE(){ ')" } -if [ -z "$REQUEST_METHOD" -a -z "$SERVER_PROTOCOL" ]; then +if [ -z "$REQUEST_METHOD" ]; then # no webserver variables means we are running via inetd / ncat # so use builtin web server @@ -173,6 +173,18 @@ URL(){ | tr , % } +PATH(){ + printf %s "$1" \ + | sed -r 's;^.*$;/&/;; s;/+;/;g; + :X; + s;^/../;/;; s;/./;/;g; + tX; + s;/[^/]+/../;/;; + tX; + s;^(/.*)/$;\1;' +} + + SET_COOKIE(){ case "$1" in ''|0|session) expire='';; -- 2.39.2 From d480b7cb55bbd085b361398bdc4903817de1709a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Paul=20H=C3=A4nsch?= Date: Thu, 5 Jul 2018 17:53:26 +0200 Subject: [PATCH 02/16] typo --- cgilite.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cgilite.sh b/cgilite.sh index 13cdb3c..6821a7a 100755 --- a/cgilite.sh +++ b/cgilite.sh @@ -200,7 +200,7 @@ SET_COOKIE(){ } REDIRECT(){ - printf '%s: %s\r\n' + printf '%s: %s\r\n' \ Status "303 See Other" \ Content-Length 0 \ Location "$*" -- 2.39.2 From 438b528a68c8638b7681e7dca95ee225d07df48d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Paul=20H=C3=A4nsch?= Date: Sat, 14 Jul 2018 22:14:39 +0200 Subject: [PATCH 03/16] unfinished storage engine --- storage.sh | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100755 storage.sh diff --git a/storage.sh b/storage.sh new file mode 100755 index 0000000..bf8b7b9 --- /dev/null +++ b/storage.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +# Copyright 2018 Paul Hänsch +# +# This is a file format helper, part of CGIlite. +# +# CGIlite is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# CGIlite is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with CGIlite. If not, see . + +# ksh and zsh workaround +case "${0##*/}" in + zsh) setopt -o OCTAL_ZEROES 2>&- ;; # zsh, mostly ignored by other shells + ksh) set -o posix ;; # ksh, will crash most other shells +esac + +STORE(){ + # Store fields from a HTTP GET or POST string in a file + # usage: STORE "${QUERY_STRING}" + # or: STORE "$(head -n $HTTP_CONTENT_LENGTH)" + # backslashes and newline characters will be escaped in field values, + # the escape symbol is a backslash + # hexadecimal character descriptions (%00 - %FF) will be expanded + # the + character will be converted to [space] + # one line in the output corresponds to exactly one field, so you can + # use grep to filter which fields of a query should be stored + printf "$( + printf '%s' "$@" \ + | sed -r ':X; $bY; N; bX; :Y; + s;\+; ;g; s;(\\|5[Cc]);\\\\\\\\;g; s;(\n|%0[Aa]);\\\\n;g; s;(^|&)([^=]+)=;\1\2:;g; s;&;\n;g; + s;^\n+;;; s;$;\\n;; s;\n+;\n;g; + # Hexadecimal { %00 - %FF } will be transformed to octal { \000 - \377 } for posix printf + s;%[0123].;&\\0;g; s;%[4567].;&\\1;g; s;%[89AB].;&\\2;g; s;%[CDEF].;&\\3;g; + s;%[048C][0-7]\\.;&0;g; s;%[048C][89A-F]\\.;&1;g; s;%[159D][0-7]\\.;&2;g; s;%[159D][89A-F]\\.;&3;g; + s;%[26AE][0-7]\\.;&4;g; s;%[26AE][89A-F]\\.;&5;g; s;%[37BF][0-7]\\.;&6;g; s;%[37BF][89A-F]\\.;&7;g; + s;%.[08](\\..);\10;g; s;%.[19](\\..);\11;g; s;%.[2A](\\..);\12;g; s;%.[3B](\\..);\13;g; + s;%.[4C](\\..);\14;g; s;%.[5D](\\..);\15;g; s;%.[6E](\\..);\16;g; s;%.[7F](\\..);\17;g; + ' + )" +} + +LOAD(){ + # read a file written by STORE and assign all fields to variables + # usage: eval "$(LOAD Date: Sun, 15 Jul 2018 14:07:22 +0200 Subject: [PATCH 04/16] locking functions --- storage.sh | 104 ++++++++++++++++++++++++++++------------------------- 1 file changed, 55 insertions(+), 49 deletions(-) diff --git a/storage.sh b/storage.sh index bf8b7b9..d4fbca3 100755 --- a/storage.sh +++ b/storage.sh @@ -17,57 +17,63 @@ # You should have received a copy of the GNU Affero General Public License # along with CGIlite. If not, see . -# ksh and zsh workaround -case "${0##*/}" in - zsh) setopt -o OCTAL_ZEROES 2>&- ;; # zsh, mostly ignored by other shells - ksh) set -o posix ;; # ksh, will crash most other shells -esac +LOCK(){ + lock="${1}.lock" + timeout="${2-20}" + if [ \! -w "${lock%/*}" ] || [ -e "$lock" -a \! -d "$lock" ]; then + printf 'Impossible to get lock: %s\n' "$lock" >&2 + return 1 + fi -STORE(){ - # Store fields from a HTTP GET or POST string in a file - # usage: STORE "${QUERY_STRING}" - # or: STORE "$(head -n $HTTP_CONTENT_LENGTH)" - # backslashes and newline characters will be escaped in field values, - # the escape symbol is a backslash - # hexadecimal character descriptions (%00 - %FF) will be expanded - # the + character will be converted to [space] - # one line in the output corresponds to exactly one field, so you can - # use grep to filter which fields of a query should be stored - printf "$( - printf '%s' "$@" \ - | sed -r ':X; $bY; N; bX; :Y; - s;\+; ;g; s;(\\|5[Cc]);\\\\\\\\;g; s;(\n|%0[Aa]);\\\\n;g; s;(^|&)([^=]+)=;\1\2:;g; s;&;\n;g; - s;^\n+;;; s;$;\\n;; s;\n+;\n;g; - # Hexadecimal { %00 - %FF } will be transformed to octal { \000 - \377 } for posix printf - s;%[0123].;&\\0;g; s;%[4567].;&\\1;g; s;%[89AB].;&\\2;g; s;%[CDEF].;&\\3;g; - s;%[048C][0-7]\\.;&0;g; s;%[048C][89A-F]\\.;&1;g; s;%[159D][0-7]\\.;&2;g; s;%[159D][89A-F]\\.;&3;g; - s;%[26AE][0-7]\\.;&4;g; s;%[26AE][89A-F]\\.;&5;g; s;%[37BF][0-7]\\.;&6;g; s;%[37BF][89A-F]\\.;&7;g; - s;%.[08](\\..);\10;g; s;%.[19](\\..);\11;g; s;%.[2A](\\..);\12;g; s;%.[3B](\\..);\13;g; - s;%.[4C](\\..);\14;g; s;%.[5D](\\..);\15;g; s;%.[6E](\\..);\16;g; s;%.[7F](\\..);\17;g; - ' - )" + while ! mkdir "$lock"; do + block="$(cat "$lock/pid" || printf 1)" + if ! { ps -eo pid |grep -qwF "$block"; }; then + printf 'Overriding stale lock: %s\n' "$lock" >&2 + break + fi + if [ $timeout -le 0 ]; then + printf 'Timeout while trying to get lock: %s\n' "$lock" >&2 + return 1 + fi + timeout=$((timeout - 1)) + sleep 1 + done + printf '%i\n' $$ >"${lock}/pid" + return 1 } -LOAD(){ - # read a file written by STORE and assign all fields to variables - # usage: eval "$(LOAD &2 + printf '%i\n' $$ >"${lock}/pid" + return 1 + fi + else + printf 'Refusing to release foreign lock: %s\n' "$lock" >&2 + return 1 + fi +} + +STRING(){ + printf %s "$*" |sed -r ' + :X; $!{N;bX;} + s;\\;\\\\;g; + s;\n;\\n;g; + s;\t;\\t;g; + s;\r;\\r;g; + ' +} - sed -r 'h; s;^[^:]+:;; - s;'\'';'\''\\'\'\'';g; - s;^.*$;'\''&'\'';; - s;\\n;\n;g; - x; s;^([^:]+):.*$;\1; - y;abcdefghijklmnopqrstuvwxyz;ABCDEFGHIJKLMNOPQRSTUVWXYZ; - s;[^A-Z0-9_];_;g; s;^.*$;_&=;; - G; s;^([A-Z0-9_]+=)\n;\1;; - ' +UNSTRING(){ + printf %s "$*" |sed -r ' + :X + s;((^|[^\\])(\\\\)*)\\n;\1\n;g; + s;((^|[^\\])(\\\\)*)\\t;\1\t;g; + s;((^|[^\\])(\\\\)*)\\r;\1\r;g; + tX; + s;\\\\;\\;g; + ' } -- 2.39.2 From 595fbc514d410ccdd46a81b8736d3711ac1ca7fe Mon Sep 17 00:00:00 2001 From: =?utf8?q?Paul=20H=C3=A4nsch?= Date: Sun, 15 Jul 2018 16:04:23 +0200 Subject: [PATCH 05/16] include guards for function libraries --- file.sh | 3 +++ storage.sh | 3 +++ 2 files changed, 6 insertions(+) diff --git a/file.sh b/file.sh index 9f734c1..06f28d0 100755 --- a/file.sh +++ b/file.sh @@ -17,6 +17,9 @@ # You should have received a copy of the GNU Affero General Public License # along with cgilite. If not, see . +[ -n "$include_fileserve" ] && return 0 +include_fileserve="$0" + file_type(){ case ${1##*.} in html|html) printf 'text/html';; diff --git a/storage.sh b/storage.sh index d4fbca3..1d8764b 100755 --- a/storage.sh +++ b/storage.sh @@ -17,6 +17,9 @@ # You should have received a copy of the GNU Affero General Public License # along with CGIlite. If not, see . +[ -n "$include_storage" ] && return 0 +include_storage="$0" + LOCK(){ lock="${1}.lock" timeout="${2-20}" -- 2.39.2 From 40c5373a1f5eb710635f340e88c31f8c9dfedfeb Mon Sep 17 00:00:00 2001 From: =?utf8?q?Paul=20H=C3=A4nsch?= Date: Sun, 15 Jul 2018 17:25:35 +0200 Subject: [PATCH 06/16] bugfix: allow positive return of LOCK() --- storage.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/storage.sh b/storage.sh index 1d8764b..8939fdc 100755 --- a/storage.sh +++ b/storage.sh @@ -42,7 +42,7 @@ LOCK(){ sleep 1 done printf '%i\n' $$ >"${lock}/pid" - return 1 + return 0 } RELEASE(){ @@ -54,6 +54,7 @@ RELEASE(){ printf '%i\n' $$ >"${lock}/pid" return 1 fi + return 0 else printf 'Refusing to release foreign lock: %s\n' "$lock" >&2 return 1 -- 2.39.2 From 813580b4cdebfe5161ef01bcbd126405c3162d7a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Paul=20H=C3=A4nsch?= Date: Sun, 15 Jul 2018 17:28:50 +0200 Subject: [PATCH 07/16] suppress error message from mkdir --- storage.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage.sh b/storage.sh index 8939fdc..f5a0ac6 100755 --- a/storage.sh +++ b/storage.sh @@ -28,7 +28,7 @@ LOCK(){ return 1 fi - while ! mkdir "$lock"; do + while ! mkdir "$lock" 2>&-; do block="$(cat "$lock/pid" || printf 1)" if ! { ps -eo pid |grep -qwF "$block"; }; then printf 'Overriding stale lock: %s\n' "$lock" >&2 -- 2.39.2 From a420ed0a86e9d315a868ea0b3eb0e965f110629f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Paul=20H=C3=A4nsch?= Date: Sun, 15 Jul 2018 21:06:28 +0200 Subject: [PATCH 08/16] escape spaces in stored data for easyer use with `read` --- storage.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/storage.sh b/storage.sh index f5a0ac6..8bd1b95 100755 --- a/storage.sh +++ b/storage.sh @@ -68,6 +68,8 @@ STRING(){ s;\n;\\n;g; s;\t;\\t;g; s;\r;\\r;g; + s;\+;\\+;g; + s; ;+;g; ' } @@ -77,7 +79,9 @@ UNSTRING(){ s;((^|[^\\])(\\\\)*)\\n;\1\n;g; s;((^|[^\\])(\\\\)*)\\t;\1\t;g; s;((^|[^\\])(\\\\)*)\\r;\1\r;g; + s;((^|[^\\])(\\\\)*)\+;\1 ;g; tX; + s;((^|[^\\])(\\\\)*)\\\+;\1+;g; s;\\\\;\\;g; ' } -- 2.39.2 From a55a4d8fb1dae783a93492c7d9b55d042791864f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Paul=20H=C3=A4nsch?= Date: Sun, 15 Jul 2018 21:54:36 +0200 Subject: [PATCH 09/16] fix: PATH function removed all directory parts shorter than two characters (pattern .. and . ;-) --- cgilite.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cgilite.sh b/cgilite.sh index 6821a7a..b936e47 100755 --- a/cgilite.sh +++ b/cgilite.sh @@ -177,9 +177,9 @@ PATH(){ printf %s "$1" \ | sed -r 's;^.*$;/&/;; s;/+;/;g; :X; - s;^/../;/;; s;/./;/;g; + s;^/\.\./;/;; s;/\./;/;g; tX; - s;/[^/]+/../;/;; + s;/[^/]+/\.\./;/;; tX; s;^(/.*)/$;\1;' } -- 2.39.2 From 318867de22a49dc1e348cc1173ee4cdeb977d7b1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Paul=20H=C3=A4nsch?= Date: Mon, 16 Jul 2018 10:46:38 +0200 Subject: [PATCH 10/16] localize fucntion variables --- cgilite.sh | 1 + file.sh | 6 +++--- storage.sh | 2 ++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/cgilite.sh b/cgilite.sh index b936e47..2930a4c 100755 --- a/cgilite.sh +++ b/cgilite.sh @@ -186,6 +186,7 @@ PATH(){ SET_COOKIE(){ + local expire cookie case "$1" in ''|0|session) expire='';; [+-][0-9]*) expire="$(date -R -d @$(($(date +%s) + $1)))";; diff --git a/file.sh b/file.sh index 06f28d0..084b7e6 100755 --- a/file.sh +++ b/file.sh @@ -1,4 +1,4 @@ -#!/bin/zsh +#!/bin/sh # Copyright 2016 - 2018 Paul Hänsch # @@ -40,7 +40,7 @@ file_type(){ } FILE(){ - unset range file_size file_date http_date cachedate + local file file_size file_date http_date cachedate range file="$1" if ! [ -f "$file" ]; then @@ -109,7 +109,7 @@ FILE(){ [ "$REQUEST_METHOD" != HEAD ] \ && tail -c+$((${range%-*} + 1)) "$file" \ - | head -c "$((${range#*-} - ${range%-*} + 1))" + | head -c "$((${range#*-} - ${range%-*} + 1))" elif [ "${range%-*}" -gt "${range#*-}" ]; then printf '%s: %s\r\n' \ diff --git a/storage.sh b/storage.sh index 8bd1b95..a6b6b43 100755 --- a/storage.sh +++ b/storage.sh @@ -21,6 +21,7 @@ include_storage="$0" LOCK(){ + local lock timeout block lock="${1}.lock" timeout="${2-20}" if [ \! -w "${lock%/*}" ] || [ -e "$lock" -a \! -d "$lock" ]; then @@ -46,6 +47,7 @@ LOCK(){ } RELEASE(){ + local lock lock="${1}.lock" if [ "$(cat "$lock/pid")" = "$$" ]; then rm "$lock/pid" -- 2.39.2 From 55052a16e5c2792b25c90b8aea0e3daea06b533a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Paul=20H=C3=A4nsch?= Date: Mon, 16 Jul 2018 12:21:13 +0200 Subject: [PATCH 11/16] minor optimisation --- file.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/file.sh b/file.sh index 084b7e6..82eefae 100755 --- a/file.sh +++ b/file.sh @@ -66,7 +66,7 @@ FILE(){ s;^[^ ]+ (...) ([0-9]) (..:..:..) ([0-9]{4})$;\4-\1-\2 \3;; s;Jan;01;; s;Feb;02;; s;Mar;03;; s;Apr;04;; s;May;05;; s;Jun;06;; s;Jul;07;; s;Aug;08;; s;Sep;09;; s;Oct;10;; s;Nov;11;; s;Dec;12;;' \ - | xargs -0 date +%s -ud 2>&- + | xargs -r0 date +%s -ud 2>&- )" range="$(HEADER Range |sed -nr 's;^bytes=([0-9]+-[0-9]*|-[0-9]+)$;\1;p;q;')" -- 2.39.2 From d45f9673ac73e57aa307db2514e6233dd673b7db Mon Sep 17 00:00:00 2001 From: =?utf8?q?Paul=20H=C3=A4nsch?= Date: Tue, 17 Jul 2018 00:59:51 +0200 Subject: [PATCH 12/16] support for "selected" keyword, improved handling of "checked" --- html-sh.sed | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/html-sh.sed b/html-sh.sed index 4af3933..1f988b3 100755 --- a/html-sh.sed +++ b/html-sh.sed @@ -44,7 +44,10 @@ s;class="([^>]+)>[ \t]+\.([^< \t]+);class="\2 \1>;g; t attribs; s;>[ \t]+\.([^< \t]+); class="\1">;g; s;>[ \t]+#([^< \t]+); id="\1">;g; s;>[ \t]+([^ \t=<]+=("[^"]*"|'[^']*'|[^< \t]*)); \1>;g; -s;(]+)>[ \t]+checked;\1 checked="checked">;g; +t attribs; +s;(]+ )?type=(radio|"radio"|'radio')( [^>]+)?)>[ \t]+checked;\1 checked="checked">;g; +s;(]+ )?type=(checkbox|"checkbox"|'checkbox')( [^>]+)?)>[ \t]+checked;\1 checked="checked">;g; +s;(]+))>[ \t]+(checked|selected);\1 selected="selected">;g; t attribs; s;(<[^/][^>]*>)[ \t]*;\1;g; -- 2.39.2 From 11d61c375b334aeb20deea101a91e970ecfd7c2a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Paul=20H=C3=A4nsch?= Date: Tue, 17 Jul 2018 01:22:51 +0200 Subject: [PATCH 13/16] bigfix: handling of [foo].bar --- html-sh.sed | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/html-sh.sed b/html-sh.sed index 1f988b3..d7a7573 100755 --- a/html-sh.sed +++ b/html-sh.sed @@ -40,14 +40,14 @@ t tagopen; G; h; s;^[^\n]*\n+;;; x; s;\n.*$;;; :attribs -s;class="([^>]+)>[ \t]+\.([^< \t]+);class="\2 \1>;g; t attribs; -s;>[ \t]+\.([^< \t]+); class="\1">;g; -s;>[ \t]+#([^< \t]+); id="\1">;g; -s;>[ \t]+([^ \t=<]+=("[^"]*"|'[^']*'|[^< \t]*)); \1>;g; +s;class="([^>]+)>[ \t]*\.([^< \t]+);class="\2 \1>;g; t attribs; +s;(<[^/][^>]*)>[ \t]*\.([^< \t]+);\1 class="\2">;g; +s;(<[^/][^>]*)>[ \t]*#([^< \t]+);\1 id="\2">;g; +s;(<[^/][^>]*)>[ \t]*([^ \t=<]+=("[^"]*"|'[^']*'|[^< \t]*));\1 \2>;g; t attribs; -s;(]+ )?type=(radio|"radio"|'radio')( [^>]+)?)>[ \t]+checked;\1 checked="checked">;g; -s;(]+ )?type=(checkbox|"checkbox"|'checkbox')( [^>]+)?)>[ \t]+checked;\1 checked="checked">;g; -s;(]+))>[ \t]+(checked|selected);\1 selected="selected">;g; +s;(]+ )?type=(radio|"radio"|'radio')( [^>]+)?)>[ \t]*checked;\1 checked="checked">;g; +s;(]+ )?type=(checkbox|"checkbox"|'checkbox')( [^>]+)?)>[ \t]*checked;\1 checked="checked">;g; +s;(]+)?)>[ \t]*(checked|selected);\1 selected="selected">;g; t attribs; s;(<[^/][^>]*>)[ \t]*;\1;g; -- 2.39.2 From 6aa432e55d9227b58dbe3d20518eb7adfa057070 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Paul=20H=C3=A4nsch?= Date: Tue, 17 Jul 2018 01:24:49 +0200 Subject: [PATCH 14/16] handlineg of ]+ )?type=(radio|"radio"|'radio')( [^>]+)?)>[ \t]*checked;\1 checked="checked">;g; s;(]+ )?type=(checkbox|"checkbox"|'checkbox')( [^>]+)?)>[ \t]*checked;\1 checked="checked">;g; s;(]+)?)>[ \t]*(checked|selected);\1 selected="selected">;g; +s;(]+)?)>[ \t]*multiple;\1 multiple="multiple">;g; t attribs; s;(<[^/][^>]*>)[ \t]*;\1;g; -- 2.39.2 From cbd426df72dee35e5920de18084ca6770454481d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Paul=20H=C3=A4nsch?= Date: Tue, 17 Jul 2018 02:06:10 +0200 Subject: [PATCH 15/16] make "checked" and "selected" keywords interchangeable --- html-sh.sed | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/html-sh.sed b/html-sh.sed index d1c70b8..514caaf 100755 --- a/html-sh.sed +++ b/html-sh.sed @@ -45,8 +45,8 @@ s;(<[^/][^>]*)>[ \t]*\.([^< \t]+);\1 class="\2">;g; s;(<[^/][^>]*)>[ \t]*#([^< \t]+);\1 id="\2">;g; s;(<[^/][^>]*)>[ \t]*([^ \t=<]+=("[^"]*"|'[^']*'|[^< \t]*));\1 \2>;g; t attribs; -s;(]+ )?type=(radio|"radio"|'radio')( [^>]+)?)>[ \t]*checked;\1 checked="checked">;g; -s;(]+ )?type=(checkbox|"checkbox"|'checkbox')( [^>]+)?)>[ \t]*checked;\1 checked="checked">;g; +s;(]+ )?type=(radio|"radio"|'radio')( [^>]+)?)>[ \t]*(checked|selected);\1 checked="checked">;g; +s;(]+ )?type=(checkbox|"checkbox"|'checkbox')( [^>]+)?)>[ \t]*(checked|selected);\1 checked="checked">;g; s;(]+)?)>[ \t]*(checked|selected);\1 selected="selected">;g; s;(]+)?)>[ \t]*multiple;\1 multiple="multiple">;g; t attribs; -- 2.39.2 From b1d4b7df6ead24f4c8e25797ae242287e73e9d59 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Paul=20H=C3=A4nsch?= Date: Tue, 17 Jul 2018 03:16:06 +0200 Subject: [PATCH 16/16] strip multi slash sequences in PATH function --- cgilite.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cgilite.sh b/cgilite.sh index 2930a4c..0c9582b 100755 --- a/cgilite.sh +++ b/cgilite.sh @@ -181,7 +181,8 @@ PATH(){ tX; s;/[^/]+/\.\./;/;; tX; - s;^(/.*)/$;\1;' + s;^(/.*)/$;\1; + s;/+;/;g;' } -- 2.39.2