The PHP function stream_is_local[0] returns FALSE when checking an encrypt stream wrapper.
The problem can be reproduced using the TCPDF[1] module, which uses the TCPDF[2] library.
The code below should generate a PDF file, but it fails since the TCPDF library verifies that the destination file is local using the stream_is_local>strong> function.
$tcpdf = tcpdf_get_instance();
$tcpdf->DrupalInitialize([]);
$tcpdf->writeHTML('<h1>Test!</h1>');
$tcpdf->Output('encrypt://encryption_profile/test.pdf', 'F');
This fails with the error Unable to create output file: encrypt://encryption_profile/test.pdf, because TCPDF checks if the output file is a local file or stream.
This happens on the fopenLocal method of the TCPDF_STATIC class (File: include/tcpdf_static.php).
public static function fopenLocal($filename, $mode) {
if (strpos($filename, '://') === false) {
$filename = 'file://'.$filename;
} elseif (stream_is_local($filename) !== true) {
return false;
}
return fopen($filename, $mode);
}
The expected result is TRUE since the encrypt stream wrapper is a local location, regardless of whether the files are encrypted.
A stream wrapper is defined as local when it is registered using the stream_wrapper_register[3], leaving the flags parameter with its default value (0).
Drupal register the stream wrappers the DrupalKernel invokes the registerWrapper method of the StreamWrapperManager class.
This method registers as local stream wrappers those wrappers whose type includes the StreamWrapperInterface::LOCAL type.
public function registerWrapper($scheme, $class, $type) {
if (in_array($scheme, stream_get_wrappers(), TRUE)) {
stream_wrapper_unregister($scheme);
}
if (($type & StreamWrapperInterface::LOCAL) == StreamWrapperInterface::LOCAL) {
stream_wrapper_register($scheme, $class);
}
else {
stream_wrapper_register($scheme, $class, STREAM_IS_URL);
}
// Pre-populate the static cache with the filters most typically used.
$info = ['type' => $type, 'class' => $class];
$this->wrappers[StreamWrapperInterface::ALL][$scheme] = $info;
if (($type & StreamWrapperInterface::WRITE_VISIBLE) == StreamWrapperInterface::WRITE_VISIBLE) {
$this->wrappers[StreamWrapperInterface::WRITE_VISIBLE][$scheme] = $info;
}
}
The StreamWrapperInterface defines the following local types:
The EncryptStreamWrapper uses StreamWrapperInterface::NORMAL as its type, so it is defined as an URL protocol by the StreamWrapperManager.
The EncryptStreamWrapper should use StreamWrapperInterface::LOCAL_NORMAL as its type, so it would be considered a local stream.
[0] https://secure.php.net/stream_is_local
[1]
https://www.drupal.org/project/tcpdf β
[2] https://tcpdf.org/
[3] https://secure.php.net/stream_wrapper_register
Not all content is available!
It's likely this issue predates Contrib.social: some issue and comment data are missing.