MediaWiki
1.34.0
img_auth.php
Go to the documentation of this file.
1
<?php
41
define(
'MW_NO_OUTPUT_COMPRESSION'
, 1 );
42
define(
'MW_ENTRY_POINT'
,
'img_auth'
);
43
require __DIR__ .
'/includes/WebStart.php'
;
44
45
# Set action base paths so that WebRequest::getPathInfo()
46
# recognizes the "X" as the 'title' in ../img_auth.php/X urls.
47
$wgArticlePath
=
false
; # Don
't let a "/*" article path clober our action path
48
$wgActionPaths = [ "$wgUploadPath/" ];
49
50
wfImageAuthMain();
51
52
$mediawiki = new MediaWiki();
53
$mediawiki->doPostOutputShutdown( '
fast
' );
54
55
function wfImageAuthMain() {
56
global $wgImgAuthUrlPathMap;
57
$permissionManager = \MediaWiki\MediaWikiServices::getInstance()->getPermissionManager();
58
59
$request = RequestContext::getMain()->getRequest();
60
$publicWiki = in_array( '
read
', $permissionManager->getGroupPermissions( [ '
*
' ] ), true );
61
62
// Get the requested file path (source file or thumbnail)
63
$matches = WebRequest::getPathInfo();
64
if ( !isset( $matches['
title
'] ) ) {
65
wfForbidden( '
img-auth-accessdenied
', '
img-auth-nopathinfo
' );
66
return;
67
}
68
$path = $matches['
title
'];
69
if ( $path && $path[0] !== '
/
' ) {
70
// Make sure $path has a leading /
71
$path = "/" . $path;
72
}
73
74
// Check for T30235: QUERY_STRING overriding the correct extension
75
$whitelist = [];
76
$extension = FileBackend::extensionFromPath( $path, '
rawcase
' );
77
if ( $extension != '
' ) {
78
$whitelist[] = $extension;
79
}
80
if ( !$request->checkUrlExtension( $whitelist ) ) {
81
return;
82
}
83
84
$user = RequestContext::getMain()->getUser();
85
86
// Various extensions may have their own backends that need access.
87
// Check if there is a special backend and storage base path for this file.
88
foreach ( $wgImgAuthUrlPathMap as $prefix => $storageDir ) {
89
$prefix = rtrim( $prefix, '
/
' ) . '
/
'; // implicit trailing slash
90
if ( strpos( $path, $prefix ) === 0 ) {
91
$be = FileBackendGroup::singleton()->backendFromPath( $storageDir );
92
$filename = $storageDir . substr( $path, strlen( $prefix ) ); // strip prefix
93
// Check basic user authorization
94
if ( !$user->isAllowed( '
read
' ) ) {
95
wfForbidden( '
img-auth-accessdenied
', '
img-auth-noread
', $path );
96
return;
97
}
98
if ( $be->fileExists( [ '
src
' => $filename ] ) ) {
99
wfDebugLog( '
img_auth
', "Streaming `" . $filename . "`." );
100
$be->streamFile( [ '
src
' => $filename ],
101
[ '
Cache-Control:
private
', '
Vary:
Cookie
' ] );
102
} else {
103
wfForbidden( '
img-auth-accessdenied
', '
img-auth-nofile
', $path );
104
}
105
return;
106
}
107
}
108
109
// Get the local file repository
110
$repo = RepoGroup::singleton()->getRepo( '
local
' );
111
$zone = strstr( ltrim( $path, '
/
' ), '
/
', true );
112
113
// Get the full file storage path and extract the source file name.
114
// (e.g. 120px-Foo.png => Foo.png or page2-120px-Foo.png => Foo.png).
115
// This only applies to thumbnails/transcoded, and each of them should
116
// be under a folder that has the source file name.
117
if ( $zone === '
thumb
' || $zone === '
transcoded
' ) {
118
$name = wfBaseName( dirname( $path ) );
119
$filename = $repo->getZonePath( $zone ) . substr( $path, strlen( "/" . $zone ) );
120
// Check to see if the file exists
121
if ( !$repo->fileExists( $filename ) ) {
122
wfForbidden( '
img-auth-accessdenied
', '
img-auth-nofile
', $filename );
123
return;
124
}
125
} else {
126
$name = wfBaseName( $path ); // file is a source file
127
$filename = $repo->getZonePath( '
public
' ) . $path;
128
// Check to see if the file exists and is not deleted
129
$bits = explode( '
!
', $name, 2 );
130
if ( substr( $path, 0, 9 ) === '
/archive/
' && count( $bits ) == 2 ) {
131
$file = $repo->newFromArchiveName( $bits[1], $name );
132
} else {
133
$file = $repo->newFile( $name );
134
}
135
if ( !$file->exists() || $file->isDeleted( File::DELETED_FILE ) ) {
136
wfForbidden( '
img-auth-accessdenied
', '
img-auth-nofile
', $filename );
137
return;
138
}
139
}
140
141
$headers = []; // extra HTTP headers to send
142
143
$title = Title::makeTitleSafe( NS_FILE, $name );
144
145
if ( !$publicWiki ) {
146
// For private wikis, run extra auth checks and set cache control headers
147
$headers['
Cache-Control
'] = '
private
';
148
$headers['
Vary
'] = '
Cookie
';
149
150
if ( !$title instanceof Title ) { // files have valid titles
151
wfForbidden( '
img-auth-accessdenied
', '
img-auth-badtitle
', $name );
152
return;
153
}
154
155
// Run hook for extension authorization plugins
157
$result = null;
158
if ( !Hooks::run( '
ImgAuthBeforeStream
', [ &$title, &$path, &$name, &$result ] ) ) {
159
wfForbidden( $result[0], $result[1], array_slice( $result, 2 ) );
160
return;
161
}
162
163
// Check user authorization for this title
164
// Checks Whitelist too
165
166
if ( !$permissionManager->userCan( '
read
', $user, $title ) ) {
167
wfForbidden( '
img-auth-accessdenied
', '
img-auth-noread
', $name );
168
return;
169
}
170
}
171
172
if ( isset( $_SERVER['
HTTP_RANGE
'] ) ) {
173
$headers['
Range
'] = $_SERVER['
HTTP_RANGE
'];
174
}
175
if ( isset( $_SERVER['
HTTP_IF_MODIFIED_SINCE
'] ) ) {
176
$headers['
If-Modified-Since
'] = $_SERVER['
HTTP_IF_MODIFIED_SINCE
'];
177
}
178
179
if ( $request->getCheck( '
download
' ) ) {
180
$headers['
Content
-Disposition
'] = '
attachment
';
181
}
182
183
// Allow modification of headers before streaming a file
184
Hooks::run( '
ImgAuthModifyHeaders
', [ $title->getTitleValue(), &$headers ] );
185
186
// Stream the requested file
187
list( $headers, $options ) = HTTPFileStreamer::preprocessHeaders( $headers );
188
wfDebugLog( '
img_auth
', "Streaming `" . $filename . "`." );
189
$repo->streamFileWithStatus( $filename, $headers, $options );
190
}
191
201
function wfForbidden( $msg1, $msg2, ...$args ) {
202
global $wgImgAuthDetails;
203
204
$args = ( isset( $args[0] ) && is_array( $args[0] ) ) ? $args[0] : $args;
205
206
$msgHdr = wfMessage( $msg1 )->escaped();
207
$detailMsgKey = $wgImgAuthDetails ? $msg2 : '
badaccess-group0
';
208
$detailMsg = wfMessage( $detailMsgKey, $args )->escaped();
209
210
wfDebugLog( '
img_auth
',
211
"wfForbidden Hdr: " . wfMessage( $msg1 )->inLanguage( '
en
' )->text() . " Msg: " .
212
wfMessage( $msg2, $args )->inLanguage( '
en
' )->text()
213
);
214
215
HttpStatus::header( 403 );
216
header( '
Cache-Control: no-cache
' );
217
header( '
Content
-Type: text/html; charset=utf-8
' );
218
echo <<<ENDS
219
<!DOCTYPE html>
220
<html>
221
<head>
222
<meta charset="UTF-8" />
223
<title>$msgHdr</title>
224
</head>
225
<body>
226
<h1>$msgHdr</h1>
227
<p>$detailMsg</p>
228
</body>
229
</html>
230
ENDS;
231
}
Content
Base interface for content objects.
Definition:
Content.php:34
$wgArticlePath
$wgArticlePath
Definition:
img_auth.php:47
Cookie
Definition:
Cookie.php:24
img_auth.php
Generated on Thu Dec 19 2019 14:54:00 for MediaWiki by
1.8.16