* Creates a share link for a file. * * @param string $folder The folder containing the shared file (or "root"). * @param string $file The name of the file being shared. * @param int $expirationSeconds The number of seconds until expiration. * @param string $password Optional password protecting the share. * @return array Returns an associative array with keys "token"
($folder, $file, $expirationSeconds = 3600, $password = "", string $createdBy = "")
| 3060 | * or "error" on failure. |
| 3061 | */ |
| 3062 | public static function createShareLink($folder, $file, $expirationSeconds = 3600, $password = "", string $createdBy = "") |
| 3063 | { |
| 3064 | try { |
| 3065 | if (FolderCrypto::isEncryptedOrAncestor((string)$folder)) { |
| 3066 | return ["error" => "Sharing is disabled inside encrypted folders."]; |
| 3067 | } |
| 3068 | } catch (\Throwable $e) { |
| 3069 | /* ignore */ |
| 3070 | } |
| 3071 | |
| 3072 | // Validate folder if necessary (this can also be done in the controller). |
| 3073 | if (strtolower($folder) !== 'root' && !preg_match(REGEX_FOLDER_NAME, $folder)) { |
| 3074 | return ["error" => "Invalid folder name."]; |
| 3075 | } |
| 3076 | // Validate file name. |
| 3077 | $file = basename(trim($file)); |
| 3078 | if (!preg_match(REGEX_FILE_NAME, $file)) { |
| 3079 | return ["error" => "Invalid file name."]; |
| 3080 | } |
| 3081 | |
| 3082 | // Generate a secure token (32 hex characters). |
| 3083 | $token = bin2hex(random_bytes(16)); |
| 3084 | |
| 3085 | // Calculate expiration (Unix timestamp). |
| 3086 | $expires = time() + $expirationSeconds; |
| 3087 | |
| 3088 | // Hash the password if provided. |
| 3089 | $hashedPassword = !empty($password) ? password_hash($password, PASSWORD_DEFAULT) : ""; |
| 3090 | |
| 3091 | // File to store share links. |
| 3092 | $shareFile = self::metaRoot() . "share_links.json"; |
| 3093 | $shareLinks = []; |
| 3094 | if (file_exists($shareFile)) { |
| 3095 | $data = file_get_contents($shareFile); |
| 3096 | $shareLinks = json_decode($data, true); |
| 3097 | if (!is_array($shareLinks)) { |
| 3098 | $shareLinks = []; |
| 3099 | } |
| 3100 | } |
| 3101 | |
| 3102 | // Clean up expired share links. |
| 3103 | $currentTime = time(); |
| 3104 | foreach ($shareLinks as $key => $link) { |
| 3105 | if ($link["expires"] < $currentTime) { |
| 3106 | unset($shareLinks[$key]); |
| 3107 | } |
| 3108 | } |
| 3109 | |
| 3110 | $createdBy = trim($createdBy); |
| 3111 | $createdBy = preg_replace('/[\x00-\x1F\x7F]/', '', $createdBy); |
| 3112 | |
| 3113 | // Add new share record. |
| 3114 | $shareLinks[$token] = [ |
| 3115 | "folder" => $folder, |
| 3116 | "file" => $file, |
| 3117 | "expires" => $expires, |
| 3118 | "password" => $hashedPassword, |
| 3119 | "createdBy" => is_string($createdBy) ? $createdBy : '', |
no test coverage detected