Posted by c960657 on January 26, 2010 at 9:04pm
7 followers
| Project: | Drupal core |
| Version: | 7.x-dev |
| Component: | image system |
| Category: | bug report |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | closed (fixed) |
Issue Summary
The GD functions imagegif(), imagepng(), and imagejpeg() do not support remote stream wrappers (e.g. imagegif($im, "s3://foo/bar.gif") fails).
image_gd_save() contains a comment related to stream wrappers and uses $wrapper->realpath() to get the local filepath:
// Convert URI to a normal path because PHP apparently has some gaps in stream wrapper support.
if ($wrapper = file_stream_wrapper_get_instance_by_uri($destination)) {
$destination = $wrapper->realpath();
}If $wrapper->realpath() returns a path that is not a filesystem path (is that allowed? The documentation for DrupalStreamWrapperInterface::realpath() isn't very explicit about the return value), the call to imagexxx() will fail.
The function needs to use a temporary path a suggested in one of the early patches for #227232: Support PHP stream wrappers, e.g. the one in comment #103.
Comments
#1
subscribe
#2
So - the suggested approach is to save to a temporary local file and then move/copy to a remote destination?
#3
Yes. Perhaps we can use some of the new stream wrapper flags that were just introduced in #685074: (Tests needed) Some stream wrappers need to be hidden or read-only.
I'm not sure I like how $wrapper->realpath() currently returns a path without wrapper prefix. This makes it difficult to normalize a path while preserving the wrapper prefix (e.g. "public://foo/bar/../baz.txt" to "public://foo/baz.txt"). Perhaps we should make the current getLocalPath() part of the DrupalLocalStreamWrapper interface and use that instead?
#4
Hmm, well we can use the local property I think.
#5
totally untested...
#6
shouldn't you use !isset($parents['DrupalLocalStreamWrapper']) rather than empty($parents['DrupalLocalStreamWrapper']) so it doesn't throw a warning if that's not set?
looks good otherwise.
#7
@aaron: the empty() check includes isset(), i.e. it doesn't throw an error if fed an uninitialized variable, so it is usually the most appropriate choice if some needed data is present...
#8
This would require alternate wrapper implementations to be subclass DrupalLocalStreamWrapper (it is an abstract class, not an interface). Would it be better to either introduce an interface or look for STREAM_WRAPPERS_LOCAL? Stream wrappers is a generic PHP feature, so a wrapper may be written for other uses than just in Drupal.
BTW whatever approach for detecting local files chosen here should also be applied to the top of archiver_get_archiver() (the logic currently in use there is flawed).
#9
#5: 696150-gd-tempnam-5.patch queued for re-testing.
#10
The last submitted patch, 696150-gd-tempnam-5.patch, failed testing.
#11
refactored to look for STREAM_WRAPPERS_LOCAL
#12
While I'm here, remove the unused $extension param from the docs. extension is part of the image object.
#13
Looks good to me.
#14
Committed to CVS HEAD. Thanks.
#15
Automatically closed -- issue fixed for 2 weeks with no activity.