[httpd, slowcgi] SBW : gzip + brotli
#26

HS : j'ai "fini" en C : https://ybad.name/pub/csbw.c
Code :
ftp https://ybad.name/pub/csbw.c
clang -o csbw csbw.c
cp csbw /var/www/cgi-bin/
+ permissions...
Par besoin de copier cat/sha256/sh ni aucune lib +  unveil + pledge.
Ça s'utilise comme le script shell.
Le code gagnerait à être factorisé. Mais c'est tout frais.

Par défaut c'est pour gzip. Pour brotli il suffit d'etiter le début du fichier.
Répondre
#27

Je t'avoue que comme le pastebin n'est pas compatible avec Iridium par défaut sur OpenBSD
(Exigence de WebAssembly ou similaire), et par flemme de naviguer dans la mini fenêtre déroulante
je n'avais pas lu le script entier …
Le problème est moins évident qu'il n'y paraîssait. Si tu ne switches pas sur csbw,
il y a la possibilité de lancer slowcgi avec "-d" dans un terminal et inverser les dièses entre "set -e"
et "set -x" en tête de script pour un aperçu plus détaillé de la source du problème.

(10-05-2020, 15:02:18)prx a écrit :  HS : j'ai "fini" en C : https://ybad.name/pub/csbw.c
(…)
Par besoin de copier cat/sha256/sh ni aucune lib +  unveil + pledge..
Je ne suis pas compétent pour en commenter le contenu
mais bravo pour l'avoir fait.
Répondre
#28

@prx, je testerais Wink
tu peux ajouter 'deflate', pour envoyer aussi du contenu gzip Wink

pour le support de br, il suffit juste de décommenter, c'est bien ça ?!

Ahh, si autre chose, auquel tu ne penses pas :
- un fichier atom peut aussi et est souvent écrit "atom.xml" donc dans ce cas-là, doit recevoir le bon mime-type Wink
- le bon mime-type pour un fichier rss semble être : application/rss+xml
- il serait intéressant de rajouter pour json : application/json :p

----

Tiens, je te propose cette modification de ta fonction content-type() :
Code :
void
content_type(const char *path)
{
    char *dot = NULL;

    dot = strrchr(path, '.');
    if (dot != NULL) {
        if (strcmp(dot, ".atom") == 0) {
            printf("Content-Type: application/atom+xml\n");
        } else if (strcmp(dot, ".css") == 0) {
            printf("Content-Type: text/css\n");
        } else if (strcmp(dot, ".html") == 0) {
            printf("Content-Type: text/html; charset=utf-8\n");
        } else if (strcmp(dot, ".js") == 0) {
            printf("Content-Type: application/javascript\n");
        } else if (strcmp(dot, ".json") == 0) {
            printf("Content-Type: application/json\n");
        } else if (strcmp(dot, ".svg") == 0) {
            printf("Content-Type: image/svg+xml;\n");
        } else if (strcmp(dot, ".txt") == 0) {
            printf("Content-Type: text/plain; charset=utf-8\n");        
        } else if (strcmp(dot, ".xml") == 0) {
            printf("Content-Type: text/xml\n");
        }
    }
}
dans l'ordre alphabétique + ajout format json
par contre, ne sachant pas comment faire pour la modifier en cas où fichier = 'atom.xml' et pour 'rss.xml...
j'ai bien compris que tu faisais une recherche par extension, donc pour ces deux fichiers ???


----

Bon, j'ai un problème avec ton csbw, @prx.
J'ai bien un status 200, mais le client web m'affiche une page blanche !!!
Quid ?

----

@eol, voilà, pour toi ce que me remonte le log :

Code :
+ set -e

+ : 86400
+ : /var/www
+ : /index.html
+ : /htdocs/my-domain.tld/dev

+ main
c'est tout, ni + ni - !
Donc, ne trouvant rien de plus, je crois que je vais arrêter de me prendre la tête ! Sad
++

----

Je dépose ma dernière version ici - on sait jamais si quelqu'un comprend pourquoi je n'arrive pas au résultat attendu - sinon tant pis !!!

Code :
#!/bin/sh
#set -x
set -e
#set -u
### ABANDONNED !!!
# sbw.cgi - 0.5
# cgi script to serve gzipped file if available with httpd.
#
# Author: prx <prx@ybad.name>
#   parts stolen from romanzolotarev here :
#   https://www.romanzolotarev.com/bin/form
#
# Collaborator: PengouinBSD <dev+bsd@huc.fr.eu.org>
#    add brotli support
#    add header Content-Length, Last-Modified, Transfer-Encoding
#
# Licence: MIT
#
# Description :
# When a file is requested, we try to deliver the gzipped file if it is present.
# i.e. index.html.gz is send instead of plain index.html
# See README
#
# chroot dependencies:
# in /var/www/bin: cat date sh sha256
# in /var/www/usr/bin: logger stat
# in /var/www/usr/lib: libc.so.* - need for stat
# in /var/www/usr/libexec: ld.so - need for stat
#
# CHANGELOG:
# Add ETag header support for better cache.
# TODO :
# * cat replacement ?
###

#PATH_INFO="index.html"
: "${cachecontrol:=3600}"
: "${chroot:=/var/www}"
: "${HTTP_IF_NONE_MATCH:=}"
: "${PATH_INFO?PATH_INFO environement variable must be set with the relative path from realroot}"
: "${realroot:=.}"

check_bin() {
    for bin in cat date sh sha256; do
        test -x "/bin/${bin}" || http500 "${bin}"
    done
    
    for bin in logger stat; do
        test -x "/usr/bin/${bin}" || http500 "${bin}"
    done
}

check_deps() {
    check_bin
    check_lib
}

check_encoding() {
    test -z "${HTTP_ACCEPT_ENCODING}" || encode=1
}

check_error() {
    if [ "${error}" -eq 0 ]; then error=200; fi
}

check_file() {
    if [ -d "${filename}" ]; then
        filename="${realroot}${PATH_INFO}index.html"
    fi
}

check_lib() {
    test -f /usr/lib/libc.so.* || http500 "/usr/lib/libc.so.*"
    test -f /usr/libexec/ld.so || http500 "/usr/libexec/ld.so"
}

check_non_match() {
    test -z "${HTTP_IF_NONE_MATCH}" && return
    if [ "${etag}" = "${HTTP_IF_NONE_MATCH}" ]; then error=304; fi
}

content_type() {
    local file="$1"
    
    case "${file}" in
        *atom.xml|*.atom) type="application/atom+xml" ;;
        *.css)  type="text/css" ;;
        *.html) type="text/html; charset=utf-8" ;;
        *.js)   type="application/javascript" ;;
        *.json)    type="application/json" ;;
        *rss.xml)    type="application/rss+xml" ;;
        *.svg)  type="image/svg+xml" ;;
        *.txt)  type="text/plain; charset=utf-8" ;;        
        *.xml)  type="text/xml" ;;    
    esac
    
    if [ "${type}" = "" ]; then
        logger "$0: Can't obtain mime-type, for this file: '${file}'!"
    fi
}

echo_status() {
    echo "Status: ${title}\n"
}

get_http() {
    local title=""
    mng_title
    
    case "${error}" in
        200) http200 ;;
        304) http304 ;;
        404) http404 ;;
        500) http500 ;;
        *)
            logger "$0: This error '${error}' is invalid!"
            exit 1
        ;;
    esac
}

html() {
    local name="$1"
    local h1="<h1>$title</h1>"
    local title="<title>$title</title>"
    
    local html_header='<!DOCTYPE html>
<head>
    <meta charset="utf-8">
    <style type="text/css">
    body { background-color: black; color: white; font-family: "Comic Sans MS", "Chalkboard SE", "Comic Neue", sans-serif; }
    h1 { color: red; font-weight: bold; }
    hr { border: 0; border-bottom: 1px dashed; }
    </style>
'
    
    local html_h2b='
</head>
<body>
'
    local html_end='
    <hr>
    <address>OpenBSD httpd</address>
</body>
'

    if [ "${name}" != "" ]; then
        local p="<p>This dependency lacks: ${name}; please, install-it into the chroot: ${chroot}</p>"
    fi
    
    local html="${html_header}\n${title}\n${html_h2b}\n${h1}\n$p\n${html_end}\n"
    
    echo "Content-Type: text/html; charset=utf-8\n"
    echo "${html}"
}

http200() {
    local type=""
    content_type "${filename}"
    
    echo_status
    if [ "${cachecontrol}" -ge 1 ]; then echo "Cache-Control: max-age=${cachecontrol}\n"; fi
    if [ "${encode}" -eq 1 ]; then echo "Content-Encoding: ${serve}\n"; fi
    if [ "${size}" -ge 1 ]; then echo "Content-Length: ${size}\n"; fi
    if [ "${type}" != "" ]; then echo "Content-Type: ${type}\n"; fi
    if [ "${etag}" != "" ]; then echo "ETag: ${etag}\n"; fi
    if [ "${mtime}" != "" ]; then echo "Last-Modified: ${mtime} GMT\n"; fi
    echo "Transfer-Encoding: chunked\n"
    echo "\n"
    
    #echo "$file"
    cat "$file"
    exit
}

http304() {
    echo_status
    exit
}

http404() {
    echo_status
    html "${filename}"
    exit
}

http500() {
    local error=500
    local name="$1"
    local title=""
    
    mng_title
    
    echo_status
    
    if [ "${name}" != "" ]; then logger "$0: This bin '${name}' lacks; please intall into chroot: '${chroot}'!"; fi
    html "${name}"
    
    exit
}

main() {
    local encode=0
    local error=0
    local etag=""
    local file=""
    local filename="${realroot}${PATH_INFO}"
    local mtime=""
    local serve=""
    local size=0
    
    check_deps
    
    check_encoding
    
    mng_file

    get_http
}

mng_file() {
    
    check_file

    if [ "${encode}" -eq 1 ]; then
        case "${HTTP_ACCEPT_ENCODING}" in
            *br*)
                file="${filename}.br"
                serve="br"
            ;;
            *deflate*|*gzip*)
                file="${filename}.gz"
                serve="gzip"
            ;;
            *)
                logger "$0: This encoding '${HTTP_ACCEPT_ENCODING}' seems invalid or not supported!"
                file="${filename}"
                serve=""
            ;;
        esac
    else
        file="${filename}"
    fi
    
    if [ -f "${file}" ]; then
        set_etag
        
        check_non_match
        
        set_mtime
        
        set_size      
        
        check_error
    else
        error=404
    fi
}

mng_title() {
    case "${error}" in
        200) title='200 OK' ;;
        304) title='304 Not Modified' ;;
        404) title='404 Not Found' ;;
        500) title='500 Internal Server Error' ;;
    esac
}

set_etag() {
    etag="$(sha256 -q "${file}")"
}

set_mtime() {
    local timestamp
    timestamp="$(stat -f"%m" "${file}")"
    mtime="$(date -r $timestamp +"%x %X")"
}

set_size() {
    size="$(stat -f"%z" "${file}")"
}

main

GPG:Fingerprint ed25519 : 072A 4DA2 8AFD 868D 74CF  9EA2 B85E 9ADA C377 5E8E
GPG:Fingerprint rsa4096 : 4E0D 4AF7 77F5 0FAE A35D  5B62 D0FF 7361 59BF 1733
Répondre
#29

Bon ce matin, je fais à nouveau des tests avec mon script CGI sh, nommé stat.cgi - histoire de le différencier du nom du script shell de @prx.

Donc, je remets le code de mon script à nouveau :
Code :
#!/bin/sh
#set -x
set -e
#set -u
### ABANDONNED !!!
# sbw.cgi - 0.5
# cgi script to serve gzipped file if available with httpd.
#
# Author: prx <prx@ybad.name>
#   parts stolen from romanzolotarev here :
#   https://www.romanzolotarev.com/bin/form
#
# Collaborator: PengouinBSD <dev+bsd@huc.fr.eu.org>
#    add brotli support
#    add header Content-Length, Last-Modified, Transfer-Encoding
#
# Licence: MIT
#
# Description :
# When a file is requested, we try to deliver the gzipped file if it is present.
# i.e. index.html.gz is send instead of plain index.html
# See README
#
# chroot dependencies:
# in /var/www/bin: cat date sh sha256
# in /var/www/usr/bin: logger stat
# in /var/www/usr/lib: libc.so.* - need for stat
# in /var/www/usr/libexec: ld.so - need for stat
#
# CHANGELOG:
# Add ETag header support for better cache.
# TODO :
# * cat replacement ?
###

#PATH_INFO="index.html"
: "${cachecontrol:=3600}"
: "${chroot:=/var/www}"
: "${HTTP_IF_NONE_MATCH:=}"
: "${PATH_INFO?PATH_INFO environement variable must be set with the relative path from realroot}"
: "${realroot:=.}"

check_bin() {
    for bin in cat date sh sha256; do
        test -x "/bin/${bin}" || http500 "${bin}"
    done
    
    for bin in logger stat; do
        test -x "/usr/bin/${bin}" || http500 "${bin}"
    done
}

check_deps() {
    check_bin
    check_lib
}

check_encoding() {
    test -z "${HTTP_ACCEPT_ENCODING}" || encode=1
}

check_error() {
    if [ "${error}" -eq 0 ]; then error=200; fi
}

check_file() {
    if [ -d "${filename}" ]; then
        filename="${realroot}${PATH_INFO}index.html"
    fi
}

check_lib() {
    test -f /usr/lib/libc.so.* || http500 "/usr/lib/libc.so.*"
    test -f /usr/libexec/ld.so || http500 "/usr/libexec/ld.so"
}

check_non_match() {
    test -z "${HTTP_IF_NONE_MATCH}" && return
    if [ "${etag}" = "${HTTP_IF_NONE_MATCH}" ]; then error=304; fi
}

content_type() {
    local file="$1"
    
    case "${file}" in
        *atom.xml|*.atom) type="application/atom+xml" ;;
        *.css)  type="text/css" ;;
        *.html) type="text/html; charset=utf-8" ;;
        *.js)   type="application/javascript" ;;
        *.json)    type="application/json" ;;
        *rss.xml)    type="application/rss+xml" ;;
        *.svg)  type="image/svg+xml" ;;
        *.txt)  type="text/plain; charset=utf-8" ;;        
        *.xml)  type="text/xml" ;;    
    esac
    
    if [ "${type}" = "" ]; then
        logger "$0: Can't obtain mime-type, for this file: '${file}'!"
    fi
}

echo_status() {
    echo "Status: ${title}\n"
}

get_http() {
    local title=""
    mng_title
    
    case "${error}" in
        200) http200 ;;
        304) http304 ;;
        404) http404 ;;
        500) http500 ;;
        *)
            logger "$0: This error '${error}' is invalid!"
            exit 1
        ;;
    esac
}

html() {
    local name="$1"
    local h1="<h1>$title</h1>"
    local title="<title>$title</title>"
    
    local html_header='<!DOCTYPE html>
<head>
    <meta charset="utf-8">
    <style type="text/css">
    body { background-color: black; color: white; font-family: "Comic Sans MS", "Chalkboard SE", "Comic Neue", sans-serif; }
    h1 { color: red; font-weight: bold; }
    hr { border: 0; border-bottom: 1px dashed; }
    </style>
'
    
    local html_h2b='
</head>
<body>
'
    local html_end='
    <hr>
    <address>OpenBSD httpd</address>
</body>
'

    if [ "${name}" != "" ]; then
        local p="<p>This dependency lacks: ${name}; please, install-it into the chroot: ${chroot}</p>"
    fi
    
    local html="${html_header}\n${title}\n${html_h2b}\n${h1}\n$p\n${html_end}\n"
    
    echo "Content-Type: text/html; charset=utf-8\n"
    echo "${html}"
}

http200() {
    local type=""
    content_type "${filename}"
    
    echo_status
    if [ "${cachecontrol}" -ge 1 ]; then echo "Cache-Control: max-age=${cachecontrol}\n"; fi
    if [ "${encode}" -eq 1 ]; then echo "Content-Encoding: ${serve}\n"; fi
    if [ "${size}" -ge 1 ]; then echo "Content-Length: ${size}\n"; fi
    if [ "${type}" != "" ]; then echo "Content-Type: ${type}\n"; fi
    if [ "${etag}" != "" ]; then echo "ETag: ${etag}\n"; fi
    if [ "${mtime}" != "" ]; then echo "Last-Modified: ${mtime} GMT\n"; fi
    echo "Transfer-Encoding: chunked\n"
    echo "\n"
    
    #echo "$file"
    cat "$file"
    exit
}

http304() {
    echo_status
    exit
}

http404() {
    echo_status
    html "${filename}"
    exit
}

http500() {
    local error=500
    local name="$1"
    local title=""
    
    mng_title
    
    echo_status
    
    if [ "${name}" != "" ]; then logger "$0: This bin '${name}' lacks; please intall into chroot: '${chroot}'!"; fi
    html "${name}"
    
    exit
}

main() {
    local encode=0
    local error=0
    local etag=""
    local file=""
    local filename="${realroot}${PATH_INFO}"
    local mtime=""
    local serve=""
    local size=0
    
    check_deps
    
    check_encoding
    
    mng_file

    get_http
}

mng_file() {
    
    check_file

    if [ "${encode}" -eq 1 ]; then
        case "${HTTP_ACCEPT_ENCODING}" in
            *br*)
                file="${filename}.br"
                serve="br"
            ;;
            *deflate*|*gzip*)
                file="${filename}.gz"
                serve="gzip"
            ;;
            *)
                logger "$0: This encoding '${HTTP_ACCEPT_ENCODING}' seems invalid or not supported!"
                file="${filename}"
                serve=""
            ;;
        esac
    else
        file="${filename}"
    fi
    
    if [ -f "${file}" ]; then
        set_etag
        
        check_non_match
        
        set_mtime
        
        set_size      
        
        check_error
    else
        error=404
    fi
}

mng_title() {
    case "${error}" in
        200) title='200 OK' ;;
        304) title='304 Not Modified' ;;
        404) title='404 Not Found' ;;
        500) title='500 Internal Server Error' ;;
    esac
}

set_etag() {
    etag="$(sha256 -q "${file}")"
}

set_mtime() {
    local timestamp
    timestamp="$(stat -f"%m" "${file}")"
    mtime="$(date -r $timestamp +"%x %X")"
}

set_size() {
    size="$(stat -f"%z" "${file}")"
}

main

Le but est d'essayer encore et toujours de comprendre pourquoi le couple httpd + slowcgi me retourne du contenu sous forme data (application octet/stream).

Pour cela, j'utilise donc les astuces fournies par @eol pour demarrer httpd et slowcgi non par l'outil rc mais à la main…

voilà ce que me restitue le serveur httpd:
Citation :# httpd -dvvv
startup
socket_rlimit: max open files 1024
socket_rlimit: max open files 1024
server_privinit: adding server default
socket_rlimit: max open files 1024
server_launch: configuring server default
server_launch: configuring server default
server_launch: running server default
server_launch: running server default
server_launch: configuring server default
server_launch: running server default
server default, client 1 (1 active), 127.0.0.1:37017 -> 127.0.0.1, closed
server default, client 1 (1 active), 127.0.0.1:47661 -> 127.0.0.1, closed
server default, client 2 (1 active), 127.0.0.1:23671 -> 127.0.0.1, closed
server default, client 1 (1 active), 127.0.0.1:9508 -> 127.0.0.1, closed
server default, client 3 (1 active), 127.0.0.1:31610 -> 127.0.0.1, closed
server default, client 4 (1 active), 127.0.0.1:1275 -> 127.0.0.1, closed
server default, client 2 (1 active), 127.0.0.1:38210 -> 127.0.0.1, closed
server default, client 5 (1 active), 127.0.0.1:34807 -> 127.0.0.1, closed
server default, client 6 (1 active), 127.0.0.1:7812 -> 127.0.0.1, closed
server default, client 7 (1 active), 127.0.0.1:20353 -> 127.0.0.1, closed
default 127.0.0.1 - - [15/May/2020:07:37:52 +0200] "GET /ecrit/ HTTP/1.1" 200 0
default 127.0.0.1 - - [15/May/2020:07:37:52 +0200] "GET /ecrit/ HTTP/1.1" 200 0
default 127.0.0.1 - - [15/May/2020:07:38:52 +0200] "<UNKNOWN> " 408 0
server default, client 8 (1 active), 127.0.0.1:9952 -> 127.0.0.1, timeout (408 Request Timeout)

Quant à slowcgi, voilà son activité :
Citation :# slowcgi -d
slowcgi: sock_user: www
slowcgi: socket: /var/www/run/slowcgi.sock
slowcgi: slowcgi_user: www
slowcgi: chroot: /var/www
slowcgi: inflight incremented, now 1
slowcgi: version: 1
slowcgi: type: 1
slowcgi: requestId: 1
slowcgi: contentLength: 8
slowcgi: paddingLength: 0
slowcgi: reserved: 0
slowcgi: role 1
slowcgi: flags 0
slowcgi: version: 1
slowcgi: type: 4
slowcgi: requestId: 1
slowcgi: contentLength: 821
slowcgi: paddingLength: 0
slowcgi: reserved: 0
slowcgi: env[0], PATH_INFO=/ecrit/
slowcgi: env[1], SCRIPT_NAME=
slowcgi: env[2], SCRIPT_FILENAME=/cgi-bin/stat.cgi
slowcgi: env[3], QUERY_STRING=
slowcgi: env[4], DOCUMENT_ROOT=/cgi-bin/stat.cgi
slowcgi: env[5], DOCUMENT_URI=/ecrit/
slowcgi: env[6], GATEWAY_INTERFACE=CGI/1.1
slowcgi: env[7], HTTP_ACCEPT=*/*
slowcgi: env[8], HTTP_ACCEPT_ENCODING=gzip, deflate
slowcgi: env[9], HTTP_ACCEPT_LANGUAGE=en-US,en;q=0.5
slowcgi: env[10], HTTP_CONNECTION=keep-alive
slowcgi: env[11], HTTP_DNT=1
slowcgi: env[12], HTTP_HOST=localhost:8080
slowcgi: env[13], HTTP_REFERER=http://localhost:8080/ecrit/
slowcgi: env[14], HTTP_USER_AGENT=Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0
slowcgi: env[15], HTTP_X_MOZ=prefetch
slowcgi: env[16], realroot=/htdocs/default/dev
slowcgi: env[17], cachecontrol=86400
slowcgi: env[18], file404=/404.html
slowcgi: env[19], realroot=/htdocs/default/dev
slowcgi: env[20], cachecontrol=86400
slowcgi: env[21], file404=/404.html
slowcgi: env[22], REMOTE_ADDR=127.0.0.1
slowcgi: env[23], REMOTE_PORT=9952
slowcgi: env[24], REQUEST_METHOD=GET
slowcgi: env[25], REQUEST_URI=/ecrit/
slowcgi: env[26], SERVER_ADDR=127.0.0.1
slowcgi: env[27], SERVER_PORT=80
slowcgi: env[28], SERVER_NAME=default
slowcgi: env[29], SERVER_PROTOCOL=HTTP/1.1
slowcgi: env[30], SERVER_SOFTWARE=OpenBSD httpd
slowcgi: version: 1
slowcgi: type: 4
slowcgi: requestId: 1
slowcgi: contentLength: 0
slowcgi: paddingLength: 0
slowcgi: reserved: 0
slowcgi: fork: /cgi-bin/stat.cgi
slowcgi: version: 1
slowcgi: type: 5
slowcgi: requestId: 1
slowcgi: contentLength: 0
slowcgi: paddingLength: 0
slowcgi: reserved: 0
slowcgi: resp version: 1
slowcgi: resp type: 6
slowcgi: resp requestId: 1
slowcgi: resp contentLength: 46
slowcgi: resp paddingLength: 2
slowcgi: resp reserved: 0
slowcgi: resp version: 1
slowcgi: resp type: 6
slowcgi: resp requestId: 1
slowcgi: resp contentLength: 226
slowcgi: resp paddingLength: 6
slowcgi: resp reserved: 0
slowcgi: resp version: 1
slowcgi: resp type: 6
slowcgi: resp requestId: 1
slowcgi: resp contentLength: 4096
slowcgi: resp paddingLength: 0
slowcgi: resp reserved: 0
slowcgi: resp version: 1
slowcgi: resp type: 6
slowcgi: resp requestId: 1
slowcgi: resp contentLength: 4096
slowcgi: resp paddingLength: 0
slowcgi: resp reserved: 0
slowcgi: resp version: 1
slowcgi: resp type: 6
slowcgi: resp requestId: 1
slowcgi: resp contentLength: 4071
slowcgi: resp paddingLength: 1
slowcgi: resp reserved: 0
slowcgi: resp version: 1
slowcgi: resp type: 6
slowcgi: resp requestId: 1
slowcgi: resp contentLength: 0
slowcgi: resp paddingLength: 0
slowcgi: resp reserved: 0
slowcgi: resp version: 1
slowcgi: resp type: 7
slowcgi: resp requestId: 1
slowcgi: resp contentLength: 0
slowcgi: resp paddingLength: 0
slowcgi: resp reserved: 0
slowcgi: wait: /cgi-bin/stat.cgi
slowcgi: resp version: 1
slowcgi: resp type: 3
slowcgi: resp requestId: 1
slowcgi: resp contentLength: 8
slowcgi: resp paddingLength: 0
slowcgi: resp reserved: 0
slowcgi: resp appStatus: 0
slowcgi: resp protocolStatus: 0
slowcgi: inflight incremented, now 1
slowcgi: version: 1
slowcgi: type: 1
slowcgi: requestId: 1
slowcgi: contentLength: 8
slowcgi: paddingLength: 0
slowcgi: reserved: 0
slowcgi: role 1
slowcgi: flags 0
slowcgi: version: 1
slowcgi: type: 4
slowcgi: requestId: 1
slowcgi: contentLength: 905
slowcgi: paddingLength: 0
slowcgi: reserved: 0
slowcgi: env[0], PATH_INFO=/ecrit/
slowcgi: env[1], SCRIPT_NAME=
slowcgi: env[2], SCRIPT_FILENAME=/cgi-bin/stat.cgi
slowcgi: env[3], QUERY_STRING=
slowcgi: env[4], DOCUMENT_ROOT=/cgi-bin/stat.cgi
slowcgi: env[5], DOCUMENT_URI=/ecrit/
slowcgi: env[6], GATEWAY_INTERFACE=CGI/1.1
slowcgi: env[7], HTTP_ACCEPT=text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
slowcgi: env[8], HTTP_ACCEPT_ENCODING=gzip, deflate
slowcgi: env[9], HTTP_ACCEPT_LANGUAGE=en-US,en;q=0.5
slowcgi: env[10], HTTP_CONNECTION=keep-alive
slowcgi: env[11], HTTP_DNT=1
slowcgi: env[12], HTTP_HOST=localhost:8080
slowcgi: env[13], HTTP_REFERER=http://localhost:8080/ecrit/
slowcgi: env[14], HTTP_UPGRADE_INSECURE_REQUESTS=1
slowcgi: env[15], HTTP_USER_AGENT=Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0
slowcgi: env[16], realroot=/htdocs/default/dev
slowcgi: env[17], cachecontrol=86400
slowcgi: env[18], file404=/404.html
slowcgi: env[19], realroot=/htdocs/default/dev
slowcgi: env[20], cachecontrol=86400
slowcgi: env[21], file404=/404.html
slowcgi: env[22], REMOTE_ADDR=127.0.0.1
slowcgi: env[23], REMOTE_PORT=9952
slowcgi: env[24], REQUEST_METHOD=GET
slowcgi: env[25], REQUEST_URI=/ecrit/
slowcgi: env[26], SERVER_ADDR=127.0.0.1
slowcgi: env[27], SERVER_PORT=80
slowcgi: env[28], SERVER_NAME=default
slowcgi: env[29], SERVER_PROTOCOL=HTTP/1.1
slowcgi: env[30], SERVER_SOFTWARE=OpenBSD httpd
slowcgi: version: 1
slowcgi: type: 4
slowcgi: requestId: 1
slowcgi: contentLength: 0
slowcgi: paddingLength: 0
slowcgi: reserved: 0
slowcgi: fork: /cgi-bin/stat.cgi
slowcgi: version: 1
slowcgi: type: 5
slowcgi: requestId: 1
slowcgi: contentLength: 0
slowcgi: paddingLength: 0
slowcgi: reserved: 0
slowcgi: resp version: 1
slowcgi: resp type: 6
slowcgi: resp requestId: 1
slowcgi: resp contentLength: 92
slowcgi: resp paddingLength: 4
slowcgi: resp reserved: 0
slowcgi: resp version: 1
slowcgi: resp type: 6
slowcgi: resp requestId: 1
slowcgi: resp contentLength: 180
slowcgi: resp paddingLength: 4
slowcgi: resp reserved: 0
slowcgi: resp version: 1
slowcgi: resp type: 6
slowcgi: resp requestId: 1
slowcgi: resp contentLength: 4096
slowcgi: resp paddingLength: 0
slowcgi: resp reserved: 0
slowcgi: resp version: 1
slowcgi: resp type: 6
slowcgi: resp requestId: 1
slowcgi: resp contentLength: 4096
slowcgi: resp paddingLength: 0
slowcgi: resp reserved: 0
slowcgi: resp version: 1
slowcgi: resp type: 6
slowcgi: resp requestId: 1
slowcgi: resp contentLength: 4071
slowcgi: resp paddingLength: 1
slowcgi: resp reserved: 0
slowcgi: resp version: 1
slowcgi: resp type: 6
slowcgi: resp requestId: 1
slowcgi: resp contentLength: 0
slowcgi: resp paddingLength: 0
slowcgi: resp reserved: 0
slowcgi: resp version: 1
slowcgi: resp type: 7
slowcgi: resp requestId: 1
slowcgi: resp contentLength: 0
slowcgi: resp paddingLength: 0
slowcgi: resp reserved: 0
slowcgi: wait: /cgi-bin/stat.cgi
slowcgi: resp version: 1
slowcgi: resp type: 3
slowcgi: resp requestId: 1
slowcgi: resp contentLength: 8
slowcgi: resp paddingLength: 0
slowcgi: resp reserved: 0
slowcgi: resp appStatus: 0
slowcgi: resp protocolStatus: 0

Voilà.
Mais aucune indication susceptible d'aider à comprendre pourquoi….
aucune trace informative des entêtes retournées !
ou toute autre information pertinente et utile… vraiment frustrant !

[Image: ekuRVAzl.png]

GPG:Fingerprint ed25519 : 072A 4DA2 8AFD 868D 74CF  9EA2 B85E 9ADA C377 5E8E
GPG:Fingerprint rsa4096 : 4E0D 4AF7 77F5 0FAE A35D  5B62 D0FF 7361 59BF 1733
Répondre
#30

Bon, avec l'aide très très très forte de @solene, sur IRC, voilà enfin une version de mon script CGI pleinement fonctionnelle :

https://framagit.org/hucste/tools/-/blob...gi/sbw.cgi

Et, ça fait vraiment plaisir ; cela nous aura permis de nous rendre compte que :
- curl sous OpenBSD n'a pas le support pour brotli, même en installant la bibliothèque ad hoc - ce qui n'est pas le cas chez Debian/Devuan
- le support de brotli, c'est bien, là, il est actif, mais dans les faits très peu de clients web l'ont - curl l'a si le support de la lib est intégré, - officiellement plusieurs clients web graphique (tel FF, FF:ESR, Chrom(e|ium),…) ont le support de br, mais quant à la gestion réelle ?! ; les clients console que sont lynx, w3m ne l'ont pas.
- qu'il est nécessaire dans les deux cas, d'envoyer une entête "Transfer-Encoding" ayant le nom de la compression…

Bref, une aventure un peu stressante, mais sympatique, surtout à partir du moment où solene m'a bien aidé à comprendre mes erreurs !
(bien sûr, je n'oublies pas les éclairages d'eol ; mais je t'ai déjà remercie) :p

GPG:Fingerprint ed25519 : 072A 4DA2 8AFD 868D 74CF  9EA2 B85E 9ADA C377 5E8E
GPG:Fingerprint rsa4096 : 4E0D 4AF7 77F5 0FAE A35D  5B62 D0FF 7361 59BF 1733
Répondre
#31

Ce matin, je livre une nouvelle version qui corrige beaucoup d'erreurs générées.
https://framagit.org/hucste/tools/-/blob...gi/sbw.cgi

- ajout d'une variable debug - si activée, retourne différentes infos sur les valeurs de variables dans le log messages
- Gestion correcte des erreurs 304, 404, 500
- Gestion correcte du type de fichier - nécessite l'ajout du binaire basename dans le chroot

Pour "y voir plus clair", j'ai renommé certaines variables, quelques fonctions…

Bogues : les flux atom et rss (atom.xml, rss.xml) ???
- avec FF, FF:ESR, ils sont bien envoyés avec le bon type correspondant - soit fil de syndication Atom ou résumé RSS - mais ils ne s'affichent pas dans le client web ; ils demandent à l'ouvrir avec une application…
- lynx, w3m cherche à dl un binaire ;
- alors qu'avec Chrome, ou curl, aucun soucis

GPG:Fingerprint ed25519 : 072A 4DA2 8AFD 868D 74CF  9EA2 B85E 9ADA C377 5E8E
GPG:Fingerprint rsa4096 : 4E0D 4AF7 77F5 0FAE A35D  5B62 D0FF 7361 59BF 1733
Répondre
#32

(16-05-2020, 06:38:51)PengouinBSD a écrit :  Bogues : les flux atom et rss (atom.xml, rss.xml) ???
- avec FF, FF:ESR, ils sont bien envoyés avec le bon type correspondant - soit fil de syndication Atom ou résumé RSS - mais ils ne s'affichent pas dans le client web ; ils demandent à l'ouvrir avec une application…
- lynx, w3m cherche à dl un binaire ;
- alors qu'avec Chrome, ou curl, aucun soucis
Si c'est envoyé avec le bon type et que ça fonctionne avec certains clients
le problème ne situerait-il pas dans la configuration des clients pour lesquels
ça ne fonctionne pas ou bien ces clients fonctionnent pour les mêmes types
lorsque que ça vient d'un autre serveur ?
Répondre
#33

ta réflexion est intéressante, mais j'avoue que pour l'instant, je n'ai pas de réponse.
Donc, test sur : https://doc.huc.fr.eu.org/fr/atom.xml et là, il s'affiche correctement dans FF !
(ce domaine m'appartient mais est hébergé ailleurs, par l'asso "L'autre.net", donc je n'ai pas la main…)

D'autant que la gestion d'un fichier tel sitemap.xml est lui-même correctement géré !
Pas de soucis avec Wink

GPG:Fingerprint ed25519 : 072A 4DA2 8AFD 868D 74CF  9EA2 B85E 9ADA C377 5E8E
GPG:Fingerprint rsa4096 : 4E0D 4AF7 77F5 0FAE A35D  5B62 D0FF 7361 59BF 1733
Répondre
#34

(16-05-2020, 14:28:01)PengouinBSD a écrit :  test sur : https://doc.huc.fr.eu.org/fr/atom.xml et là, il s'affiche correctement dans FF !
Parfait !
Maintenant
Code :
curl --compressed -I https://doc.huc.fr.eu.org/fr/atom.xml
curl --compressed -s https://doc.huc.fr.eu.org/fr/atom.xml |file -b -
pareil pour l'URL qui ne fonctionne pas et plus qu'à espérer
qu'une différence utile à un diagnostic apparaîsse.
Répondre
#35

Code :
$ curl --compressed -I https://doc.huc.fr.eu.org/fr/atom.xml
HTTP/2 200
date: Sat, 16 May 2020 14:06:37 GMT
content-type: application/xml
last-modified: Fri, 15 May 2020 14:34:36 GMT
etag: "1679c2-5a5b0b65e1700-gzip"
accept-ranges: bytes
vary: Accept-Encoding
content-encoding: gzip
content-security-policy: upgrade-insecure-requests
x-backend-server: 10.0.0.41:80
Code :
$ curl --compressed -s https://doc.huc.fr.eu.org/fr/atom.xml |file -b -
XML 1.0 document, UTF-8 Unicode text, with very long lines
Code :
curl -H "Accept-Encoding: deflate, gzip" -I http://ebnh.fr.eu.org/atom.xml
HTTP/1.1 200 OK
Cache-Control: public, max-age=86400
Connection: keep-alive
Content-Encoding: gzip
Content-Type: application/atom+xml
Date: Sat, 16 May 2020 14:09:08 GMT
ETag: 8f06eb794a24d8d26129d4d6aa281ebb14e75d2b85e615edd241267b5f2eba71
Feature-Policy: fullscreen 'self'; accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; payment 'none'; usb 'none'
Frame-Options: SAMEORIGIN
Last-Modified: Sat May 16 08:01:44 GMT 2020
Referrer-Policy: strict-origin
Server: OpenBSD Relayd+httpd
Transfer-Encoding: gzip
Transfer-Encoding: chunked
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Frame-Options: SAMEORIGIN
X-Powered-By: e-Brain!
X-Robots-Tag: index, nofollow
x-ua-compatible: IE=edge,chrome=1
X-Xss-Protection: 1; mode=block
Code :
$ curl -H "Accept-Encoding: deflate, gzip" -I http://ebnh.fr.eu.org/atom.xml |file -b -
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
ASCII text, with CRLF line terminators

alors que localement, sur mon ordi avant transfert :
Code :
$ file public/atom.xml
public/atom.xml: XML 1.0 document, UTF-8 Unicode text, with very long lines

GPG:Fingerprint ed25519 : 072A 4DA2 8AFD 868D 74CF  9EA2 B85E 9ADA C377 5E8E
GPG:Fingerprint rsa4096 : 4E0D 4AF7 77F5 0FAE A35D  5B62 D0FF 7361 59BF 1733
Répondre
#36

Il y a une différence dans le content-type envoyé, c'est déjà une piste à creuser.
Je ne sais pas si ça a une quelconque importance (je ne pense pas)
mais l'un envoie le nom des en-têtes avec une Majuscule en premier et
l'autre tout en minuscules.
Répondre
#37

je vais vérifier la piste de la casse s'il y a une importance réelle ?!

Réponse à cette question :
Aucune importance !
cf: https://tools.ietf.org/html/rfc7230#section-3.2
Citation :Each header field consists of a case-insensitive field name followed
by a colon (":"), optional leading whitespace, the field value, and
optional trailing whitespace.

Selon la page WP :
https://en.wikipedia.org/wiki/List_of_HT...der_fields
Citation :Header field names are case-insensitive.[2] This is in contrast to HTTP method names (GET, POST, etc.), which are case-sensitive[3][4].
https://tools.ietf.org/html/rfc7230#section-3.1.1
Citation :The method token indicates the request method to be performed on the
target resource. The request method is case-sensitive.

C'est bon à savoir ! :p

GPG:Fingerprint ed25519 : 072A 4DA2 8AFD 868D 74CF  9EA2 B85E 9ADA C377 5E8E
GPG:Fingerprint rsa4096 : 4E0D 4AF7 77F5 0FAE A35D  5B62 D0FF 7361 59BF 1733
Répondre
#38

(16-05-2020, 15:54:56)PengouinBSD a écrit :  Aucune importance !
Tant mieux.
Plus qu'à vérifier ce qui a une éventuelle importance alors … ;p

Juste un commentaire, lors d'une comparaison
il est souhaitable d'observer exactement le même protocole
envers les différents objets afin d'être certain de ne pas introduire
soi-même une variable supplémentaire. (Je n'affirme pas que
tu en as introduit une cette fois-ci, c'est juste une remarque
qui me vient en voyant que tu as utilisé des invocations différentes
de curl pour chaque URL). De par sa formation @prx serait meilleur
que moi pour expliquer ce qu'est un bon protocole expérimental
mais je ne pense pas m'être trop égaré avec le commentaire ci-dessus.

(08-05-2020, 13:25:48)prx a écrit :  Servir du contenu précompressé est proposé ici : https://github.com/reyk/httpd/issues/80

https://github.com/reyk/httpd/issues/21 qui est taggué "featuritis" par le développeur
et référencé dans le premier message de https://github.com/reyk/httpd/issues/80
Reyk a écrit :No.

You can use gzip in fastcgi backends but static files will not be served with compression.
Too many problems are know from other web servers, and people tend to turn it off again.
me semble montrer que l'utilisateur est invité à aborder ce problème via fastcgi
comme tu l'as fait avec succès.

Le posteur original de #80 pense que cette invitation ne s'applique
qu'à la compression dynamique. Il a peut-être raison, ou pas …
Répondre
#39

En fait les deux failles BREACH & CRIME sont des failles dues à la compression à la volée du contenu délivré, qui touche même TLS.
https://en.wikipedia.org/wiki/BREACH

C'est pour cela qu'il est recommandé dans les pratiques de sécurité de ne pas compresser le contenu à la demande par le serveur web - ce que d'aucuns serveurs web savent très bien faire.
Pour contourner le "problème", c'est justement de mettre à disposition le contenu sous format compressé en sus du contenu "plain", le serveur n'ayant plus qu'à le délivrer si le contenu compressé existe. Ainsi, le serveur web ne cherche pas à compresser le contenu à délivrer, donc pas d'injection de code pirate, mais délivre seulement le contenu compressé, si adéquate.
Ainsi, on utilise pas le protocole de compression HTTP.

Nous pouvons nous permettre de délivrer du contenu compressé parce qu'il est statique ; apparemment, il ne faudrait pas le faire avec du contenu généré dynamiquement, à moins de mettre le prix sur plus d'une combine sécurisante. Et, encore ?!

Une des parades depuis HTTP1.1 est le transfert d'encodage par bloc - la fameuse déclaration d'entête : Transfer-Encoding: chunked Wink
Une autre est de mettre en place la politique Referrer - même si dans certaines conditions, il serait possible de les "spoofer"...
Il est intéressant de lire que certaines recommandations pour la politique Referrer est la suivante : si le contenu délivré est produit par le domaine ciblé alors contenu compressé, si ce n'est pas le cas, alors pas de compression.

Cela permet de comprendre les raisons et réticences légitimes de Reyk - et il a raison de dire qu'il y a eu beaucoup de problèmes.

Même si nous pouvons espérer que les "fabriquants" de client web est modifier leur code pour contrer ce genre de failles...
Même si les "fabriquants" de serveur web ont corrigé leur code pour ne plus en être victime, que les développeurs d'OpenSSL ont amélioré le leur…
Même s'il est clair que délivrer du contenu static compressé est à-priori, encore actuellement, sans faille connue, donc sans danger ; un jour peut-être...

Bref, il est très prudent de limiter l'usage de délivrance de contenu compressé au contenu statique, et d'utiliser en sus une politique referrer, - ne pas oublier cette dernière - jusqu'au jour où…

----

Oui, j'ai utilisé des invocations différentes pour la simple raison après avoir testé - et je ne l'ai pas indiqué, certes - l'usage de curl avec l'option compressed sur le second serveur, c'est le contenu 'br' qui était retourné, donc les entêtes "content-encoding" et "transfer-encoding" différaient d'un contenu délivré en gzip.
donc, pour avoir la similtude de réponse, en spécifiant l'entête en option de curl juste sur les formats de compression "deflate, gzip", j'avais un retour similaire d'entête de réponse à celles du premier serveur !
(j'espère être clair sur mon explication) :p

GPG:Fingerprint ed25519 : 072A 4DA2 8AFD 868D 74CF  9EA2 B85E 9ADA C377 5E8E
GPG:Fingerprint rsa4096 : 4E0D 4AF7 77F5 0FAE A35D  5B62 D0FF 7361 59BF 1733
Répondre
#40

(17-05-2020, 02:26:07)PengouinBSD a écrit :  En fait les deux failles BREACH & CRIME sont des failles dues à la compression à la volée du contenu délivré, qui touche même TLS.
https://en.wikipedia.org/wiki/BREACH
(…)
Ok, j'avais pas pris le temps de creuser. Ce que tu écris confirme que le posteur original
avait sûrement raison de présumer que les réticences du développeur ne s'applique
qu'à la compression dynamique.

(17-05-2020, 02:26:07)PengouinBSD a écrit :  Oui, j'ai utilisé des invocations différentes pour la simple raison après avoir testé - et je ne l'ai pas indiqué, certes - l'usage de curl avec l'option compressed sur le second serveur, c'est le contenu 'br' qui était retourné, donc les entêtes "content-encoding" et "transfer-encoding" différaient d'un contenu délivré en gzip.
donc, pour avoir la similtude de réponse, en spécifiant l'entête en option de curl juste sur les formats de compression "deflate, gzip", j'avais un retour similaire d'entête de réponse à celles du premier serveur !
(j'espère être clair sur mon explication) :p
Oui, je crois comprendre. Tu as fait différent pour que ce soit pareil. ;p

Concernant les différences de réaction au contenu côté client,
c'est plus sur la différence existante de valeur de l'en-tête content-type
que je creuserais pour application/atom+xml et application/xml soit dans
un éventuel fichier mimeapps.list ou équivalent dans ton $HOME ou /etc
ou bien dans la configuration de firefox.
Chez moi, sans que je n'aie configuré quoi que ce soit à ce propos
je vois des différences :
Code :
xdg-mime query default application/xml
firefox.desktop
tandis que
Code :
xdg-mime query default application/atom+xml
ne retourne rien du tout.
Répondre
#41

En fait le type mime que je déclare est connu, reconnu, fixé par une RFC ou l'autre.

Ces formats sont connus du serveur httpd :
Code :
# grep -E "atom|rss" /usr/share/misc/mime.types
application/atom+xml                    atom
application/rss+xml                    rss

il en est de même pour le mime type du language XHTML, dérivé du XML : application/xhtml+xml

Mais par contre, pour tout autre contenu au format XML, tel un fichier sitemap.xml, le mime type correspondant est : application/xml

Sauf bien-sûr, si tu veux délivrer du format Open Document, voire OpenOffice XML, qui ont chacun leur propre mime type.

Chacun ayant sa RFC.

---

Bref, si dans mon script CGI, je m'assure qu'il soit correctement défini, normalement je ne devrais pas avoir à le faire puisque le serveur httpd sait reconnaître le format et normalement le diffuser avec la bonne entête "content-type'.
Je le fais, par assurance ! Wink
(histoire de bien faire les choses…)

GPG:Fingerprint ed25519 : 072A 4DA2 8AFD 868D 74CF  9EA2 B85E 9ADA C377 5E8E
GPG:Fingerprint rsa4096 : 4E0D 4AF7 77F5 0FAE A35D  5B62 D0FF 7361 59BF 1733
Répondre
#42

(17-05-2020, 13:23:58)PengouinBSD a écrit :  En fait le type mime que je déclare est connu, reconnu, fixé par une RFC ou l'autre.
Je ne remets pas en cause ta configuration côté serveur.
Avec
(17-05-2020, 12:55:16)eol a écrit :  tandis que
Code :
xdg-mime query default application/atom+xml
ne retourne rien du tout.
j'essaie d'attirer ton attention sur le fait que si toi non plus tu n'as rien configuré explicitement
pour "application/atom+xml" il est possible que *côté client* ça patine.
Répondre
#43

En effet, c'est possible :p
;-)

GPG:Fingerprint ed25519 : 072A 4DA2 8AFD 868D 74CF  9EA2 B85E 9ADA C377 5E8E
GPG:Fingerprint rsa4096 : 4E0D 4AF7 77F5 0FAE A35D  5B62 D0FF 7361 59BF 1733
Répondre
#44

Concernant FF, est-ce qu'il n'y aurait pas de cela, justement ?!
https://support.mozilla.org/fr/kb/rempla...ux-firefox

après test, si j'envoie le flux atom en text/xml, FF le lit bel et bien ; si je l'envoie avec le bon mime type, il demande à l'ouvrir avec un autre lecteur... ! pfff
délicate décision à prendre !

GPG:Fingerprint ed25519 : 072A 4DA2 8AFD 868D 74CF  9EA2 B85E 9ADA C377 5E8E
GPG:Fingerprint rsa4096 : 4E0D 4AF7 77F5 0FAE A35D  5B62 D0FF 7361 59BF 1733
Répondre
#45

bon, ce soir, j'ai finalisé une nouvelle version, un peu avec l'aide certaine de solene, de mon script ; cette version, si installée, permet de tricher avec FF(ESR?) si version >= 64 !

Attention, cette deuxième version, à la différence de la première nécessite en dépendance en plus les deux outils que sont awk et grep !

https://framagit.org/hucste/tools/-/blob...i/sbw2.cgi

GPG:Fingerprint ed25519 : 072A 4DA2 8AFD 868D 74CF  9EA2 B85E 9ADA C377 5E8E
GPG:Fingerprint rsa4096 : 4E0D 4AF7 77F5 0FAE A35D  5B62 D0FF 7361 59BF 1733
Répondre
#46

Tu as copié grep et awk + les libs associées dans ton chroot du coup ?
Répondre
#47

Pour l'utilisation qui en est faite, ni awk, ni grep, ni basename ne sont nécessaires.
L'expansion de paramètres
Code :
man -O tag=Expansion sh
et test à doubles crochets
suffisent.
Répondre
#48

@prx: oui

@eol: ahhh, c'est vrai. Je testerai ça :p

GPG:Fingerprint ed25519 : 072A 4DA2 8AFD 868D 74CF  9EA2 B85E 9ADA C377 5E8E
GPG:Fingerprint rsa4096 : 4E0D 4AF7 77F5 0FAE A35D  5B62 D0FF 7361 59BF 1733
Répondre
#49

Bon, OK, donc j'ai retravaillé mon code pour n'utiliser que l'expansion shell. Donc, bye-bye awk et perl.
Du fait, je ne rediffuse qu'un seul script CGI. 

Merci @ed.

https://framagit.org/hucste/tools/-/raw/...gi/sbw.cgi

GPG:Fingerprint ed25519 : 072A 4DA2 8AFD 868D 74CF  9EA2 B85E 9ADA C377 5E8E
GPG:Fingerprint rsa4096 : 4E0D 4AF7 77F5 0FAE A35D  5B62 D0FF 7361 59BF 1733
Répondre
#50

ooooh, bien joué!
En plus, le code est propre, j'aime bien Smile
Répondre


Atteindre :


Utilisateur(s) parcourant ce sujet : 1 visiteur(s)