Include Nextcloud calendar in a PicoCMS page

This is proving very stubborn. Here is where I’m at:

I have the embed link for my calendar:

https://mynextcloud.tld/index.php/apps/calendar/embed/kXwQ72R54o9d3aYP/dayGridMonth/now

I can load that in the browser. Looks good.

I tried adding:

<iframe width="400" height="215" frame-src="https://my/index.php/apps/calendar/embed/kXwQ72R54o9d3aYP"></iframe>

to a .md PicoCMS page. This doesn’t work.

I am slowly aware that Nextcloud filters out pretty much all but the most basic HTML from .md files before rendering them as HTML to the client/browser on the basis of security concerns. The general advcie is to move it into the .twig template. And that generally works. So I move it to the .twig template. But it still doesn’t work.

Now I’m gettinng annoyed, so I look press F12 and start debugging in my browser. I can see the HTML is rendered as:

<iframe frame-src="https://mynextcloud.tld/index.php/apps/calendar/embed/kXwQ72R54o9d3aYP" width="400" height="215"></iframe>

Albeit Firefox’ debugger renders an oddity in inside its Inspector that is seemingly “not there” as in can’t be copied out, so an image is best I can manage:

Hmm, nothing conspicuous on the console. To be very sure I check the response headers and security with:

$ curl -i https://mynextcloud.tld/index.php/apps/cms_pico/pico/pico_test/Events
HTTP/1.1 200 OK
Set-Cookie: ocnsjvv2rmtc=gcbjl05p89ogrbl720ehtqrb1g; path=/; secure; HttpOnly; SameSite=Lax
Set-Cookie: oc_sessionPassphrase=MiV7zIL671814aZi1C3OQuVe4H1gRdHzU8naTKreslx5ytJZHqZt4n6QkhI1d%2BhKUmosUbADVaPyFNIVMzK0%2FT5tEWUmnZuRurkjim%2Fczyjm6lCB%2FnHxJxPwDU%2B4yPBB; path=/; secure; HttpOnly; SameSite=Lax
Set-Cookie: __Host-nc_sameSiteCookielax=true; path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=lax
Set-Cookie: __Host-nc_sameSiteCookiestrict=true; path=/; httponly;secure; expires=Fri, 31-Dec-2100 23:59:59 GMT; SameSite=strict
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Pragma: no-cache
Referrer-Policy: no-referrer
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Frame-Options: SAMEORIGIN
X-Permitted-Cross-Domain-Policies: none
X-Robots-Tag: none
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, must-revalidate
Content-Disposition: inline; filename=""
Content-Security-Policy: default-src 'self'; frame-src 'self'; child-src 'self'; base-uri 'none'; manifest-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' https://fonts.googleapis.com 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self' data: https://fonts.googleapis.com https://fonts.gstatic.com; connect-src 'self'; media-src 'self'; object-src 'self';
Feature-Policy: autoplay 'none';camera 'none';fullscreen 'none';geolocation 'none';microphone 'none';payment 'none'
Content-Length: 3034
Content-type: text/html; charset=UTF-8
Strict-Transport-Security: max-age=15552000
Date: Sun, 06 Sep 2020 02:36:52 GMT
Server: lighttpd/1.4.55

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Events Calendar | Pico Test</title>
          <link rel="icon" type="image/png" href="/index.php/apps/cms_pico/pico/pico_test/assets-5f4c54b39c6ca/favicon.ico"/>
  
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:400,700" type="text/css" />
  <link rel="stylesheet" href="/apps/cms_pico/appdata_public/themes/3QKFyZaF0b/just-pico/css/pure-min.css" type="text/css" />
  <link rel="stylesheet" href="/apps/cms_pico/appdata_public/themes/3QKFyZaF0b/just-pico/css/style.css" type="text/css" />

    </head>
<body class="page">
    <div id="layout">
    <!-- Menu toggle -->
    <a href="#menu" id="menuLink" class="menu-link">
      <!-- Hamburger icon -->
      <span></span>
    </a>
    <header id="menu">
      <div class="pure-menu">
        <a id="logo" class="pure-menu-heading" href="/index.php/apps/cms_pico/pico/pico_test/">
                      Pico Test
                  </a>
        <!-- <h4></h4> -->
        <ul class="pure-menu-list">
                                    <li class="pure-menu-item ">
                <a href="/index.php/apps/cms_pico/pico/pico_test/" class="pure-menu-link">Welcome</a>
              </li>
                                                <li class="pure-menu-item pure-menu-selected">
                <a href="/index.php/apps/cms_pico/pico/pico_test/Events" class="pure-menu-link">Events Calendar</a>
              </li>
                                                <li class="pure-menu-item ">
                <a href="/index.php/apps/cms_pico/pico/pico_test/sub" class="pure-menu-link">Sub Page Index</a>
              </li>
                                                <li class="pure-menu-item ">
                <a href="/index.php/apps/cms_pico/pico/pico_test/sub/page" class="pure-menu-link">Sub Page</a>
              </li>
                                                <li class="pure-menu-item ">
                <a href="/index.php/apps/cms_pico/pico/pico_test/theme" class="pure-menu-link">Theme Styling Test</a>
              </li>
                              </ul>
      </div>
    </header>


  <main>
    <div class="header">
        <h1>Events Calendar</h1>
            </div>
        <div class="content">
            <hr><iframe width="400" height="215" frame-src="https://mynextcloud.tld/index.php/apps/calendar/embed/kXwQ72R54o9d3aYP"></iframe>
<hr>      <p><b>Bold Test</b></p>
<p><a href="xxx">An HTML link</a></p>
<p>End of File</p>
    </div>
  </main>

    <footer id="footer" class="pure-g">
      <div class="inner pure-u-1">
        Powered by <a href="http://picocms.org/">Pico</a> CMS &ndash;
        With Just Pico template by <a href="http://blocknot.es">mat</a>.
      </div>
    </footer>
  </div> <!-- layout closing -->
  <div id="overlay"></div>
  <script src="/apps/cms_pico/appdata_public/themes/3QKFyZaF0b/just-pico/js/main.js"></script>
</body>
</html>

Of particular note:

X-Frame-Options: SAMEORIGIN

looks good.

Content-Security-Policy: default-src 'self'; frame-src 'self'; child-src 'self'; base-uri 'none'; manifest-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' https://fonts.googleapis.com 'unsafe-inline'; img-src 'self' data: blob:; font-src 'self' data: https://fonts.googleapis.com https://fonts.gstatic.com; connect-src 'self'; media-src 'self'; object-src 'self';

looks good. The content saecurity policy is long and hard to read so formatted for nicely (line break after every semicolon) to facilitate comprehension:

Content-Security-Policy: default-src 'self';
 frame-src 'self';
 child-src 'self';
 base-uri 'none';
 manifest-src 'self';
 script-src 'self' 'unsafe-inline' 'unsafe-eval';
 style-src 'self' https://fonts.googleapis.com 'unsafe-inline';
 img-src 'self' data: blob:;
 font-src 'self' data: https://fonts.googleapis.com https://fonts.gstatic.com;
 connect-src 'self';
 media-src 'self';
 object-src 'self';

Still looks good to me, (thouygh I’m no pro).

So what could be preventing my calendary loading in this iframe? I se nly the reserved space for it but not content.

To be sure, in the Network debugger I also see no requets made to fecth its contents, nor do I see any such request in the enabled access log on the Nextcloud server.

It seems clear the Firefox (nor Chrome) doesn’t load the iframe URL at all, nor doe sit complain about content securiyt policy. Slowly I’m just frustrated and beyond my know how here. As in what could be causing this? And what further diagnostics can I do?

Shouldn’t it be

<iframe src="https://mynextcloud.tld/index.php/apps/calendar/embed/kXwQ72R54o9d3aYP" width="400" height="215"></iframe>

instead of

<iframe frame-src="https://mynextcloud.tld/index.php/apps/calendar/embed/kXwQ72R54o9d3aYP" width="400" height="215"></iframe>

?

Aaargh! Well spotted. Now it works. I started with src., I used fame-src at some point during experiments to try and find a working solution, and failed to switch back. Bizarre that the FF console doesn’t report a missing attribute! C’est la vie. Am so pleased it finally works.

I think at the outset the Content-Security-Policy was wrong and it took some reading and playing around to get it right, but I forgot about that attr experiment in the mean time. And that is what an independent set of eyes are so useful to spot (and well documented problem case for them to consider). So high five, thanks for the spot and glad I posted with a good rundown to enable it.

But I have found another problem and I suspect it’s insider the Calendar app. Essentially it would be nice to size this iframe in such a way that the whole embedded calendar fits without any scroll bars. But it turns out that:

  1. The calendar app is in fact smart and scales it’s default (month) view to fit into whatever sized iFrame I specify. Nice.
  2. Not so nice is that it always has a vertical scroll bar. And this is because the embedded caledar link (if loaded in hte browser as a URL proper) in fact renders that way. it is fit into the browser window but has a vertical scroll bar which is there probably as a bug! Because it look to be that the month cells occupy the whole window ignoring the presence of the header on the calendar, and because the header is added it grows a smidgeon and this scroll bar shows. Looks to me like a Calendar app bug.