32 $permissionManager = $services->getPermissionManager();
35 $publicWiki = $services->getGroupPermissionsLookup()->groupHasPermission(
'*',
'read' );
38 $baseUrl = $services->getRepoGroup()->getLocalRepo()->getZoneUrl(
'public' );
39 if ( $baseUrl[0] ===
'/' ) {
42 $basePath = parse_url( $baseUrl, PHP_URL_PATH );
46 if (
$path ===
false ) {
53 if (
$path ===
false ) {
54 $this->forbidden(
'img-auth-accessdenied',
'img-auth-notindir' );
68 foreach ( $pathMap as $prefix => $storageDir ) {
69 $prefix = rtrim( $prefix,
'/' ) .
'/';
70 if ( str_starts_with(
$path, $prefix ) ) {
71 $be = $services->getFileBackendGroup()->backendFromPath( $storageDir );
72 $filename = $storageDir . substr(
$path, strlen( $prefix ) );
74 $isAllowedUser = $permissionManager->userHasRight( $user,
'read' );
75 if ( !$isAllowedUser ) {
76 $this->forbidden(
'img-auth-accessdenied',
'img-auth-noread',
$path );
79 if ( $be && $be->fileExists( [
'src' => $filename ] ) ) {
80 wfDebugLog(
'img_auth',
"Streaming `" . $filename .
"`." );
83 'headers' => [
'Cache-Control: private',
'Vary: Cookie' ]
86 $this->forbidden(
'img-auth-accessdenied',
'img-auth-nofile',
$path );
94 $repo = $services->getRepoGroup()->getLocalRepo();
95 $zone = strstr( ltrim(
$path,
'/' ),
'/',
true );
101 if ( $zone ===
'thumb' || $zone ===
'transcoded' ) {
103 $filename = $repo->getZonePath( $zone ) . substr(
$path, strlen(
"/" . $zone ) );
105 if ( !$repo->fileExists( $filename ) ) {
106 $this->forbidden(
'img-auth-accessdenied',
'img-auth-nofile', $filename );
111 $filename = $repo->getZonePath(
'public' ) .
$path;
113 $bits = explode(
'!', $name, 2 );
114 if ( str_starts_with(
$path,
'/archive/' ) && count( $bits ) == 2 ) {
115 $file = $repo->newFromArchiveName( $bits[1], $name );
117 $file = $repo->newFile( $name );
119 if ( !$file || !$file->exists() || $file->isDeleted( File::DELETED_FILE ) ) {
120 $this->forbidden(
'img-auth-accessdenied',
'img-auth-nofile', $filename );
127 $title = Title::makeTitleSafe(
NS_FILE, $name );
129 $hookRunner =
new HookRunner( $services->getHookContainer() );
130 if ( !$publicWiki ) {
132 $headers[
'Cache-Control'] =
'private';
133 $headers[
'Vary'] =
'Cookie';
135 if ( !$title instanceof
Title ) {
136 $this->forbidden(
'img-auth-accessdenied',
'img-auth-badtitle', $name );
142 if ( !$hookRunner->onImgAuthBeforeStream( $title,
$path, $name, $authResult ) ) {
143 $this->forbidden( $authResult[0], $authResult[1], array_slice( $authResult, 2 ) );
147 if ( !$permissionManager->userCan(
'read', $user, $title ) ) {
148 $this->forbidden(
'img-auth-accessdenied',
'img-auth-noread', $name );
153 $range = $this->environment->getServerInfo(
'HTTP_RANGE' );
154 $ims = $this->environment->getServerInfo(
'HTTP_IF_MODIFIED_SINCE' );
156 if ( $range !==
null ) {
157 $headers[
'Range'] = $range;
159 if ( $ims !==
null ) {
160 $headers[
'If-Modified-Since'] = $ims;
163 if ( $request->getCheck(
'download' ) ) {
164 $headers[
'Content-Disposition'] =
'attachment';
167 $cspHeader = ContentSecurityPolicy::getMediaHeader( $filename );
169 $headers[
'Content-Security-Policy'] = $cspHeader;
173 $hookRunner->onImgAuthModifyHeaders( $title->getTitleValue(), $headers );
179 wfDebugLog(
'img_auth',
"Streaming `" . $filename .
"`." );
180 $repo->streamFileWithStatus( $filename, $headers, $options );