getgrav / grav-plugin-form

Grav Form Plugin

Home Page:http://getgrav.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

basic-captcha not showing image (404)

prismplex opened this issue · comments

Description of the issue:

Captcha image is not displayed using basic-captcha in a modular page.
human

Investigation:

Console throws: Failed to load resource: the server responded with a status of 404 () trying to reach captcha image via https://url.com/forms-basic-captcha-image.jpg?v=1663798282900

Current setup:

Modular page, reachable via https://url.com/de/contact

Working configuration before embedding basic captcha:

title: 'Contact form'
form:
    action: /contact
    name: contact-form
    fields:
        -
            name: name
            label: Name
            placeholder: 'Your name'
            autocomplete: 'on'
            type: text
            validate:
                required: true
        -
            name: firstname
            label: 'First Name'
            placeholder: 'Ihr Vorname'
            type: honeypot
        -
            name: email
            label: Email
            placeholder: 'Your email adress'
            type: email
            validate:
                required: true
        -
            name: message
            label: Message
            placeholder: 'Your message'
            type: textarea
            validate:
                required: true
        -
            name: terms
            label: 'I have read, understood and accepted the privacy policy.'
            type: checkbox
            validate:
                required: true
    buttons:
        -
            type: submit
            value: Submit
        -
            type: reset
            value: Reset
    process:
        -
            email:
                from: '{{ config.plugins.email.from }}'
                to:
                    - '{{ config.plugins.email.from }}'
                    - '{{ form.value.email }}'
                subject: '[Contact] {{ form.value.name|e }}'
                body: '{% include ''forms/data.html.twig'' %}'
        -
            save:
                fileprefix: feedback-
                dateformat: Ymd-His-u
                extension: txt
                body: '{% include ''forms/data.txt.twig'' %}'
        -
            message: 'Danke für Ihre Nachricht!'
        -
            display: thankyou

New configuration:

title: 'Contact form'
form:
    action: /contact
    name: contact-form
    fields:
        -
            name: name
            label: Name
            placeholder: 'Your name'
            autocomplete: 'on'
            type: text
            validate:
                required: true
        -
            name: firstname
            label: 'First Name'
            placeholder: 'Ihr Vorname'
            type: honeypot
        -
            name: email
            label: Email
            placeholder: 'Your email adress'
            type: email
            validate:
                required: true
        -
            name: message
            label: Message
            placeholder: 'Your message'
            type: textarea
            validate:
                required: true
        -
            name: terms
            label: 'I have read, understood and accepted the privacy policy.'
            type: checkbox
            validate:
                required: true
        -
            name: basic-captcha
            type: basic-captcha
            placeholder: 'Bitte kopieren Sie die 10 Zahlen oder Buchstaben'
            label: 'Are you human?'
    buttons:
        -
            type: submit
            value: Submit
        -
            type: reset
            value: Reset
    process:
        -
            basic-captcha:
                message: 'Humanity verification failed, please try again...'
        -
            email:
                from: '{{ config.plugins.email.from }}'
                to:
                    - '{{ config.plugins.email.from }}'
                    - '{{ form.value.email }}'
                subject: '[Contact] {{ form.value.name|e }}'
                body: '{% include ''forms/data.html.twig'' %}'
        -
            save:
                fileprefix: feedback-
                dateformat: Ymd-His-u
                extension: txt
                body: '{% include ''forms/data.txt.twig'' %}'
        -
            message: 'Danke für Ihre Nachricht!'
        -
            display: thankyou

Am I missing something?

I think its more likely an issue of the multilang config (/de)causing the route not to be found, i'll investigate.

well, i can't replicate this on my test environment with multi-language enabled, and with a modular form. Works fine for me. Is it possible for me to inspect your site in my browser and see the actual issue?

Image is neither reachable via https://url.com/contact/forms-basic-captcha-image.jpg?v=1663800272971/https://url.com/_contact/forms-basic-captcha-image.jpg?v=1663800272971 nor https://url.com/de/forms-basic-captcha-image.jpg?v=1663800272971 or https://url.com/de/contact/forms-basic-captcha-image.jpg?v=1663800272971/https://url.com/de/_contact/forms-basic-captcha-image.jpg?v=1663800272971

It should work fine as https://url.com/forms-basic-captcha-image.jpg?v=1663798282900 which is where it's expecting it, and what you originally had. That's why i need to see your site 'live' to inspect the request/response.

Take my username, add .io (switch to English) and go to the contact site.

Very strange, it's like you are missing some code. Can you confirm you have this at the bottom of your user/plugins/form/form.php file:

    protected function processBasicCaptchaImage(Uri $uri)
    {
        if ($uri->path() === '/forms-basic-captcha-image.jpg') {
            $captcha = new BasicCaptcha();
            $code = $captcha->getCaptchaCode();
            $image = $captcha->createCaptchaImage($code);
            $captcha->renderCaptchaImage($image);
            exit;
        }
    }

Actually did you create this 404 error page?
CleanShot 2022-09-21 at 17 08 04@2x

Is it grav that's outputting that? doesn't really look like it, it's like something is intercepting 404 and grav is not getting the chance to resolve that URL.

Definitely seems like your webserver is handling errors for images independently from documents/pages, and that's causing this issue. any request for an arbitrary .jpg or .png (/foo.jpg) is getting this error, where any made up page gets the Grav error page (/foo).

Very strange, it's like you are missing some code. Can you confirm you have this at the bottom of your user/plugins/form/form.php file:

    protected function processBasicCaptchaImage(Uri $uri)
    {
        if ($uri->path() === '/forms-basic-captcha-image.jpg') {
            $captcha = new BasicCaptcha();
            $code = $captcha->getCaptchaCode();
            $image = $captcha->createCaptchaImage($code);
            $captcha->renderCaptchaImage($image);
            exit;
        }
    }

Did not have this code, added it at the end. Installed forms shows version v7.0.1

Actually did you create this 404 error page? CleanShot 2022-09-21 at 17 08 04@2x

Is it grav that's outputting that? doesn't really look like it, it's like something is intercepting 404 and grav is not getting the chance to resolve that URL.

Yes, I created it, but removed it now to show that that is (in my opinion) not the problem, as the webserver only outputs 404 if the file is not found.

I am using the nginx config from the official GRAV documentation.

https://github.com/getgrav/grav-plugin-form/blob/7.0.1/form.php#L1279-L1288

If you have 7.0.1 you should have this method, see the link above. If you copy that in there does it work??

https://github.com/getgrav/grav-plugin-form/blob/7.0.1/form.php#L1279-L1288

If you have 7.0.1 you should have this method, see the link above. If you copy that in there does it work??

That is really strange... - Thinking about reinstalling GRAV.
Copied it, cleared full cache, still does not work.

Deleted full form folder under plugins, reinstalled, verified the existance function (it is there) - cleared full cache - still not working...

Frankly i would look at your nginx config, and if there's any error page stuff there, comment them out. I don't have any nginx test environments handy, but i've tested with Apache, Litespeed, and bulit-in PHP webserver and those are all fine.

My nginx config:

server {
listen 80;
listen [::]:80;
server_name url.com www.url.com;
return 301 https://url.com$request_uri;
}

server {
  listen 127.0.0.1:443 ssl http2;
  listen [::1]:443 ssl http2;
  server_name url.com www.url.com;

    ssl_certificate /home/user/.acme.sh/url.com/fullchain.pem;
    ssl_certificate_key /home/user/.acme.sh/url.com/privkey.pem;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    include conf.d/grav-security.conf;
    include conf.d/general.conf;
    #include conf.d/error.conf;

    #Logging accesses and errors - change to PATH according your needs
    access_log /home/user/conf/nginx.log/access.url.com.log;
    error_log /home/user/conf/nginx.log/error.url.com.log;

    # Path to the root of your installation
    root /home/user/nginx/grav-url.com;

    index index.php index.html index.htm /_h5ai/public/index.php;
   
    ## Begin - Index
    # for subfolders, simply adjust:
    # `location /subfolder {`
    # and the rewrite to use `/subfolder/index.php`
    location / {
        try_files $uri $uri/ /index.php?_url=$uri&$query_string;
    }
    ## End - Index

    ## Begin - Security
    # deny all direct access for these folders
    location ~* /(.git|cache|bin|logs|backup|tests)/.*$ { return 403; }
    # deny running scripts inside core system folders
    location ~* /(system|vendor)/.*\.(txt|xml|md|html|yaml|php|pl|py|cgi|twig|sh|bat)$ { return 403; }
    # deny running scripts inside user folder
    location ~* /user/.*\.(txt|md|yaml|php|pl|py|cgi|twig|sh|bat)$ { return 403; }
    # deny access to specific files in the root folder
    location ~ /(LICENSE.txt|composer.lock|composer.json|nginx.conf|web.config|htaccess.txt|\.htaccess) { return 403; }
    ## End - Security

    ## Begin - PHP
    location ~ \.php$ {
        # Choose either a socket or TCP/IP address
        # fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_pass 127.0.0.1:portnumber;

        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
    }
    ## End - PHP

    include conf.d/grav.conf;
}

general.conf

	# favicon.ico
	location = /favicon.ico {
	    log_not_found off;
	    access_log    off;
	}

	# robots.txt
	location = /robots.txt {
	    log_not_found off;
	    access_log    off;
	}

        client_max_body_size 16G; # set max upload size depending on your desires
        fastcgi_buffers 64 4K;

	# gzip
	gzip            on;
	gzip_vary       on;
	gzip_proxied    any;
	gzip_comp_level 6;
	#gzip_types      text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;
	gzip_types
	    application/atom+xml
	    application/javascript
	    application/json
	    application/ld+json
	    application/manifest+json
	    application/rss+xml
	    application/vnd.geo+json
	    application/vnd.ms-fontobject
	    application/x-font-ttf
	    application/x-web-app-manifest+json
	    application/xhtml+xml
	    application/xml
	    font/opentype
	    image/bmp
	    image/svg+xml
	    image/x-icon
	    text/cache-manifest
	    text/css
	    text/plain
	    text/vcard
	    text/vnd.rim.location.xloc
	    text/vtt
	    text/x-component
	    text/x-cross-domain-policy;

grav-security.conf

add_header Referrer-Policy                      "no-referrer"   always;
add_header X-Content-Type-Options               "nosniff"       always;
add_header X-Download-Options                   "noopen"        always;
add_header X-Frame-Options                      "SAMEORIGIN"    always;
add_header X-Permitted-Cross-Domain-Policies    "none"          always;
add_header X-Robots-Tag                         "none"          always;
add_header X-XSS-Protection                     "1; mode=block" always;
add_header Permissions-Policy                   "interest-cohort=()" always;
fastcgi_hide_header                             X-Powered-By;

# force the latest IE version
add_header "X-UA-Compatible" "IE=Edge";

# Use a higher keepalive timeout to reduce the need for repeated handshakes
keepalive_timeout 300s; # up from 75 secs default

ssl_session_cache shared:SSL:10m; # a 1mb cache can hold about 4000 sessions, so we can hold 40000 sessions
ssl_session_timeout 24h;

# submit domain for preloading in browsers at: https://hstspreload.appspot.com
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;

grav.conf

	location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
                expires 30d;
                add_header Vary Accept-Encoding;
                log_not_found off;
        }

        location ~* ^.+\.(?:css|cur|js|jpe?g|gif|htc|ico|png|html|xml|otf|ttf|eot|woff|woff2|svg)$ {
                access_log off;
                expires 30d;
                add_header Cache-Control public;

		## No need to bleed constant updates. Send the all shebang in one
		## fell swoop.
                tcp_nodelay off;

		## Set the OS file cache.
                open_file_cache max=3000 inactive=120s;
                open_file_cache_valid 45s;
                open_file_cache_min_uses 2;
                open_file_cache_errors off;
        }

I really don't know where the problem here could be, as it is basically all copoied from the official GRAV documentation...

After some testing I found the problem.
After disabling

grav.conf

	location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
                expires 30d;
                add_header Vary Accept-Encoding;
                log_not_found off;
        }

        location ~* ^.+\.(?:css|cur|js|jpe?g|gif|htc|ico|png|html|xml|otf|ttf|eot|woff|woff2|svg)$ {
                access_log off;
                expires 30d;
                add_header Cache-Control public;

		## No need to bleed constant updates. Send the all shebang in one
		## fell swoop.
                tcp_nodelay off;

		## Set the OS file cache.
                open_file_cache max=3000 inactive=120s;
                open_file_cache_valid 45s;
                open_file_cache_min_uses 2;
                open_file_cache_errors off;
        }

everything works as expected, captcha images are showing

I have the same problem when running Grav in docker with image lscr.io/linuxserver/grav:latest.
I will check if the solution from @prismplex does also fix the issue for me.

EDIT: it appears that the same configuration also exists in this docker image (file config/nginx/site-confs/default.conf) and by disabling these same lines the issue is fixed. Everything seems to work including the captcha image.

👍🏻

Why close this issue without an answer?

I had the same problem when using the official directives provided by Grav for Nginx.

I deleted jpe?g from the regex lists, but I would like to put it back and find which parameter break basic-captcha.

Why close this issue without an answer?

I had the same problem when using the official directives provided by Grav for Nginx.

I deleted jpe?g from the regex lists, but I would like to put it back and find which parameter break basic-captcha.

I also would like to use the basic captcha, but I got same issue in case of GPDR. Sure, I could change the grav.conf file, but in case that I'm using lscr.io/linuxserver/grav:latest in docker, that's no right solution.

It seems like adding:

    location ~* ^/forms-basic-captcha-image.jpg$ {
        try_files $uri $uri/ /index.php$is_args$args;
    }

to the top of grav.conf (or in the lsio conf, add it right below ## Begin - Caching) resolves the issue. I will open PRs for this.

@nemchik you made my day! Thx for the fix, it works!