silverstripe / silverstripe-assets

Silverstripe Assets component
BSD 3-Clause "New" or "Revised" License
9 stars 67 forks source link

Allow type-specific image manpulation handlers, build one for SVG #65

Open sminnee opened 7 years ago

sminnee commented 7 years ago

By default, SVG files should be given a specialised and much simpler handler. SVG are at least as much a part of the internet as ReactJS and if SS4 was impossible to use to build ReactJS-based sites we'd think it's a bit broken. ;)

First up, this requires that image manipulation handlers can be plugged in for specific types, probably, with a fail-over to a default handler. Ideally, this could mean that other file types could have variant processors included (e.g. you might have a PDF handler that produces plaintext) but that's not a requirement for this use-case.

As for the SVG handler, we can keep things simple:

My hope/expectation is that this level of functionality would be possible without a SVG parser.

sminnee commented 7 years ago

A couple of approaches for type-specific image backends:

tractorcow commented 7 years ago

Instead of ImageBackendDispatcher we put the logic into the existing ImageBackendFactory? It already supports conditional creation as well as caching based on SHA / filename.

tractorcow commented 7 years ago

Replace:

if ($store->exists() && $store->getIsImage()) {
    $backend = $this->creator->create($service, $params);
}

With

if ($store->exists() && $store->getIsImage()) {
    $service = $this->backendFor(File::get_extension($store->getFilename()));
    $backend = $this->creator->create($service, $params);
}
tractorcow commented 7 years ago

YML config:

---
Name: assetsimage
---
SilverStripe\Core\Injector\Injector:
  SilverStripe\Assets\ImageBackendFactory:
    constructor:
      creator: '%$SilverStripe\Core\Injector\InjectionCreator'
  SilverStripe\Assets\Image_Backend:
    class: SilverStripe\Assets\InterventionBackend
    factory: '%$SilverStripe\Assets\ImageBackendFactory'
  SilverStripe\Assets\Image_Backend.svg:
    class: SilverStripe\Assets\SvgBackend

All the logic would be in ImageBackendFactory, which could conditionally delegate back to a more precise service via injector.

tractorcow commented 7 years ago
if ($store->exists() && $store->getIsImage()) {
    $ext = File::get_extension($store->getFilename());
    $serviceExt = Image_Backend::class.'.'.$ext;
    if ($ext && Config::inst()->get(Injector::class, $serviceExt)) {
        $backend = Injector::inst()->createWithArgs($serviceExt, $params);
    } else {
      $backend = $this->creator->create($service, $params);
    }
}
sminnee commented 7 years ago

Yeah, seems reasonable to put it into ImageBackendFactory.

maxime-rainville commented 5 years ago

We disallow SVG upload out of the box, because it's a security risk. Is it really worth it adding convenience methods for a file types we don't technically support?

sminnee commented 5 years ago

It was a couple of years since we wrote this; at the time the discussion was about trying to allow for some kind of module that would scrub SVG. If you’re looking to prune the list of enhancements I’d probably roll everything up into a “support user-uploaded SVG in essentials recipe” story or something like that, close all these tickets that are specific solution ideas, and link to the closed tickets from that umbrella ticket.

Or we could just close it. I acknowledge that blocking SVGs breaks user-expectations, even though it’s tricky to solve securely.