Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,10 @@ VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

# DISABLE_IMPORT_FROM_SERVER=false

# On shared hosting where sys_get_temp_dir() is not readable/writable,
# set to false to use storage/tmp/uploads_parts instead.
# USE_SYSTEM_TEMP_DIR=true

# When enabled, the request caching settings (cache_enabled, cache_ttl,
# cache_event_logging) become visible in the admin settings panel.
# ENABLE_REQUEST_CACHING=false
Expand Down
6 changes: 3 additions & 3 deletions app/Actions/Diagnostics/Pipes/Checks/IniSettingsCheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,15 @@ public function handle(array &$data, \Closure $next): array
}
// @codeCoverageIgnoreEnd

$path = sys_get_temp_dir();
$path = Helpers::getTmpDir();
if (!is_writable($path)) {
// @codeCoverageIgnoreStart
$data[] = DiagnosticData::error('sys_get_temp_dir() is not writable, this will prevent you from uploading pictures.', self::class);
$data[] = DiagnosticData::error('The temp directory (' . $path . ') is not writable, this will prevent you from uploading pictures. Set USE_SYSTEM_TEMP_DIR=false in .env to use storage/tmp/uploads_parts instead.', self::class);
// @codeCoverageIgnoreEnd
}
if (!is_readable($path)) {
// @codeCoverageIgnoreStart
$data[] = DiagnosticData::error('sys_get_temp_dir() is not readable, this will prevent you from uploading pictures.', self::class);
$data[] = DiagnosticData::error('The temp directory (' . $path . ') is not readable, this will prevent you from uploading pictures. Set USE_SYSTEM_TEMP_DIR=false in .env to use storage/tmp/uploads_parts instead.', self::class);
// @codeCoverageIgnoreEnd
}

Expand Down
4 changes: 4 additions & 0 deletions app/Actions/InstallUpdate/DefaultConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ public function __construct()
$this->config['requirements']['php'][] = $db_possibility[1];
}
}

if (config('features.use-system-temp-dir') === false) {
$this->config['permissions']['storage/tmp/uploads_parts/'] = 'file_exists|is_readable|is_writable|is_executable';
}
// @codeCoverageIgnoreStart
} catch (BindingResolutionException|ContainerExceptionInterface $e) {
throw new FrameworkException('Laravel\'s container component', $e);
Expand Down
21 changes: 21 additions & 0 deletions app/Assets/Helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Safe\Exceptions\FilesystemException;
use Safe\Exceptions\InfoException;
use function Safe\ini_get;
use function Safe\mkdir;
use function Safe\rmdir;
use function Safe\unlink;

Expand Down Expand Up @@ -42,6 +43,26 @@ public function trancateIf32(string $id, int $prev_short_id = 0, int $php_max =
return (string) $short_id;
}

/**
* Return the temporary directory path used for uploads.
*
* When features.use-system-temp-dir is true (default), returns sys_get_temp_dir().
* Otherwise returns storage/tmp/uploads_parts, creating it if needed.
*/
public function getTmpDir(): string
{
if (config('features.use-system-temp-dir', true) === true) {
return sys_get_temp_dir();
}

$path = storage_path('tmp/uploads_parts');
if (!file_exists($path)) {
mkdir($path, 0755, true);
}
Comment thread
ildyria marked this conversation as resolved.

return $path;
}

/**
* Check if $path has readable and writable permissions.
*/
Expand Down
1 change: 1 addition & 0 deletions app/Facades/Helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*
* Keep the list of documented method in sync with {@link \App\Assets\Helpers}.
*
* @method static string getTmpDir()
* @method static string trancateIf32(string $id, int $prevShortId = 0, int $php_max)
* @method static string getExtension(string $filename, bool $isURI = false)
* @method static bool hasPermissions(string $path)
Expand Down
3 changes: 2 additions & 1 deletion app/Image/Files/TemporaryLocalFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
namespace App\Image\Files;

use App\Exceptions\MediaFileOperationException;
use App\Facades\Helpers;

/**
* Class TemporaryLocalFile.
Expand Down Expand Up @@ -53,7 +54,7 @@ public function __construct(
*/
protected function getFileBasePath(): string
{
return sys_get_temp_dir();
return Helpers::getTmpDir();
}

/**
Expand Down
3 changes: 2 additions & 1 deletion app/Image/Handlers/ImagickHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use App\DTO\ImageDimension;
use App\Exceptions\ImageProcessingException;
use App\Exceptions\MediaFileOperationException;
use App\Facades\Helpers;
use App\Image\Files\FlysystemFile;
use App\Image\Files\InMemoryBuffer;
use App\Image\Files\NativeLocalFile;
Expand Down Expand Up @@ -105,7 +106,7 @@ private function loadPdf(MediaFile $file): void
// .pdf path so Ghostscript recognises the format by extension. The outer
// try/finally guarantees the .pdf temp file is cleaned up even if fopen(),
// stream_copy_to_stream(), or readImage() throws.
$tmp_base = tempnam(sys_get_temp_dir(), 'lychee_');
$tmp_base = tempnam(Helpers::getTmpDir(), 'lychee_');
$tmp_path = $tmp_base . '.pdf';
rename($tmp_base, $tmp_path);
$pdf_path = $tmp_path;
Expand Down
11 changes: 11 additions & 0 deletions config/features.php
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,17 @@
*/
'use_fopen_for_url_imports' => (bool) env('USE_FOPEN_FOR_URL_IMPORTS', false),

/*
|--------------------------------------------------------------------------
| Use system temp directory for uploads
|--------------------------------------------------------------------------
|
| When enabled, Lychee uses PHP's sys_get_temp_dir() for temporary upload
| files. On shared hosting where that directory is not readable/writable,
| set USE_SYSTEM_TEMP_DIR=false to use storage/tmp/uploads_parts instead.
*/
'use-system-temp-dir' => (bool) env('USE_SYSTEM_TEMP_DIR', true),

/*
|--------------------------------------------------------------------------
| Enable Request Caching
Expand Down
Loading