Twig function calendar_link is not working with views

Steps to reproduce

1. Install a standard drupal(9.0.0), make sure the views(9.0.0) and views UI is enabled.
2. Install calendar_link using composer
3. Create a test article content.
4. Create a test view showing "content" of type "article" with "fields", display "page"
5. Add field "Global: custom text" and put this code in it and hit save.

{% set link = calendar_link('ics', 'testing title', date('Nov 16, 2021'), date('Nov 17, 2021'), FALSE, 'testing description', 'houston') %}
<a href="{{ link }}">Add to Calendar</a>

6. In the output you would see the link but it doesn't download the .ics file, the reason for that is the href is getting updated and it removed the "data:" string from the output.
7. If you put the same above code in page.html.twig then it works perfectly fine.

Please see the screenshots for the same.

Comments

bakulahluwalia created an issue. See original summary.

bakulahluwalia’s picture

Priority: Normal » Major
wells’s picture

This looks to be a core issue with how data scheme URLs are handled. When rendering the View fields, Drupal\Component\Utility\UrlHelper::stripDangerousProtocols is called on the link generated by the field and it strips data: because that is not a whitelisted protocol. Apparently that particular method is not called on links added directly to templates.

I can't seem to dig up any issues or code/comments that specifically say data: should be treated as insecure, but doing so does make sense.

See also #3040688: Url::fromUri($uri)->isExternal() and UrlHelper::isExternal($uri) do not always match. Somewhat related, though it doesn't do anything to solve this issue.

Unfortunately it seems like this just isn't possible without a core patch that supports the data scheme in a secure way and that could be somewhat complex. Perhaps this module's README and description needs to be updated to note that link adding is only supported in templates.

bakulahluwalia’s picture

@wells Thanks for the update. Not sure if I would like to wait for core team to provide a fix/patch. Here is an alternative that worked for me if anyone else facing the same:
New code in views twig:

{% set link = calendar_link('ics', 'testing title', date('Nov 16, 2021'), date('Nov 17, 2021'), FALSE, 'testing description', 'houston') %}
<div class="myCal" data="{{ link }}">Add to Calendar</div>

Add these lines in javascript:

Drupal.behaviors.cal = {
  attach: function (context, settings) {
    var $ = jQuery;
    $('.myCal').click(function(item) {
      var str = item.target.attributes.data.value;
      var res = str.replace("data:text/calendar;charset=utf8;base64,", "");
      window.open( "data:text/calendar;charset=utf8," + escape(res));
    });
  }
};

Thanks again for the quick response @wells, not sure how would you like to handle this ticket. The js solution can also be implemented in this module as well.

wells’s picture

Assigned: Unassigned » wells
Priority: Major » Normal
Status: Active » Postponed

I'll leave this ticket open for now. I'm thinking of creating a core issue and patch to address this and your workaround may be useful for others (though I don't want to take that path for the module itself). Thanks for providing it!

benjarlett’s picture

hmm.. any clues on how to add this javascript?

wells’s picture

@benjarlett you would need to implement it as a library and then attach that library wherever you need the code to run.

The easiest place to do this would probably be in your theme. You would create the library there and attach it in a template with the attach_library function. Take a look at Adding stylesheets (CSS) and JavaScript (JS) to a Drupal theme for some guidance on that.

benjarlett’s picture

Thanks, sounds beyond me though.

wells’s picture

Status: Postponed » Closed (works as designed)
liquidcms’s picture

deleted.