Adjusting the media hash generation

I just realized the media hash generation has been changed with Kirby 3.4.0 after a client nervously told me they were sharing the file URLs from the file view and they’re not working anymore. Of course it’s a bad idea to share the hashed file URLs but I can’t really blame him clicking on the URL link in the file view.

Is there any way I can go back to the old hash generation? Unfortunately I can’t even fix this with redirecting routes because the media folder is excluded. Please correct me if I’m wrong.

Digging through the core code and some pull requests it seems like this line changed: kirby/App.php at 38afb2d650f3764d23d732b23ae8f04ab9ffba69 · getkirby/kirby · GitHub

Changing this back to crc32($model->filename()) . '-' . $model->modifiedFile() seems to revert the change. Is there any way I can extend this method? I don’t want to edit stuff in the /kirby folder for obvious reasons.

Thanks in advance for any help in this matter!

1 Like

Not sure, but maybe you can achieve this through the file::url component?

That sounds like a good idea. I will try this and report back. Thanks for the quick answer!

I used the following code now:

<?php

Kirby::plugin('my/fileUrls', [
  'components' => [
      'file::url' => function (Kirby $kirby, $file, array $options = []) {
          return $file->parent()->mediaUrl() . '/' . crc32($file->filename()) . '-' . F::modified($file->root()) . '/' . $file->filename();
      }
  ]
]);

There seems to be a discrepancy between the modified time but I’ll try to sort this out. It looks like a good solution for now.

Ok, so this isn’t the solution as it seems :frowning:

While the file URLs are correctly overwritten they result in a “Not found” message. The file::url component seems to only overwrite the url() function, not making sure the file can actually be accessed. The documentation says (…) can be used to let thumbnails be generated on different services like Cloudinary or Imgix, but it can also be used to host files in a different location and load them from there. so I suppose it’s used to modify the url() to match such a service.

I’d appreciate any help how to overwrite the contentToken() function in src/Cms/App.php, because I think that’s what I have to do. Essentially changing return hash_hmac('sha1', $value, $salt); to return crc32($model->filename());.

Hm. If I understand correct, you have files with hashed filenames by method 1 and now the method changed and your files need to be accessed with the hash of method 2 in the filename (which is known and still the same)? In this case you could implement a rewrite rule with a map function which implements the translation from one hash to the other.

@Adspectus Thanks for your suggestion. As far as I know I can‘t redirect the media URLs. The routes get ignored.

I do not mean routes in Kirby, just plain rewrite rules for the webserver rewrite engine, but, as I mentioned, it might be that I do not fully understand the problem.

Ah, I see. I can‘t access the modified time/hash there. Manually putting hundreds of rewrite rules is not an option either. Well, maybe the last option? :sweat_smile:

@thguenther This is a hack more than an elegant solution and I haven’t tested it, but as this thought just crossed my mind: could it be a “second-last” option to deal with this in the error handling?

I assume calls to the expired image URLs cause a 404 error. Could you intercept 404s in a way that you check whether the failed URL is a media file, only then calculate the new URL that matches the expired one and return a 301 redirecting to that URL instead?

Thats indeed not an option. If it is not solvable by means of a RewriteMap (http://httpd.apache.org/docs/2.4/rewrite/rewritemap.html) it is to expensive.

Yeah, I tried this too. It’s super weird and maybe I found a Kirby bug but it’s all so over my head I’m not 100% sure. Here it comes:

If the file is found but the media hash is wrong it displays “Not found” instead of the regular Kirby error page. Making it impossible for me to react.

📁 page
   📃 file.pdf

example.com/media/pages/page/f4a9f1c30b-1612523451/file.pdf
→ Actual URL

example.com/media/pages/page/f4a9f1c30b-1612523451/nonsense.pdf
→ Kirby error page

example.com/media/pages/page/123456789/file.pdf
→ Weird “Not found” page

Ah, I had a hunch (both that you already investigated this path, and that it’s not as straightforward as it appears).

Interestingly, a NotFoundException (the “Not found” text) only occurs when dealing with an original file’s media URL. Running the same experiment on a thumb version of an image (file name ends with -300x-q70.jpg), the Kirby error page is displayed if the hash is wrong. (Not that this knowledge would help you, just to document in case this is being looked into.)

Without any knowledge about the design rationale or technical reasons behind this, I would lean towards framing this as a bug, or at least a inconsistency worth addressing in a future update? After all, a site owner may want to be able to display a custom error page when somebody uses an expired media URL.

For your problem at hand, I don’t have any further ideas at this point :no_mouth:

Thanks so much for testing this yourself and spending time on my issue, Sebastian!

I have yet to find the code responsible for triggering the exception but after reading you could reproduce the NotFoundException page instead of a normal error page I’m almost 100% sure this is not intended.

This behavior of a plain “Not Found” message is indeed not great, especially since it’s a one line fix to make Kirby render the error page instead.

I’ve converted this discussion into one issue and one PR:

The media implementation has two separate cases:

  • If the hash itself is invalid (which is only based on the file path and the content.salt Kirby option), this means that the whole URL is invalid and could never have been correct. For security, Kirby then displayed “Not Found” until now, but of course it doesn’t harm to display the error page. This is actually even better to avoid leaking that the file exists at all.
  • If the hash is correct, but the timestamp is invalid, Kirby redirects to the new updated URL. No custom error page needed.

Basically the only thing we missed in the new implementation are URLs with the old hash format.

2 Likes

Hello! Thanks for this thread: It brought me on the right track for updating an older template with the error only occuring once image fields were updated.

This problem is especially annoying due to the code needing to switch between legacy media paths with slugs and the new file:// prefix in the same template.

Probably a reminder not to apply custom data wrangling too loosely.

1 Like