Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/files/controller/PhabricatorFileTransformController.php
12242 views
1
<?php
2
3
final class PhabricatorFileTransformController
4
extends PhabricatorFileController {
5
6
public function shouldRequireLogin() {
7
return false;
8
}
9
10
public function handleRequest(AphrontRequest $request) {
11
$viewer = $this->getViewer();
12
13
// NOTE: This is a public/CDN endpoint, and permission to see files is
14
// controlled by knowing the secret key, not by authentication.
15
16
$is_regenerate = $request->getBool('regenerate');
17
18
$source_phid = $request->getURIData('phid');
19
$file = id(new PhabricatorFileQuery())
20
->setViewer(PhabricatorUser::getOmnipotentUser())
21
->withPHIDs(array($source_phid))
22
->executeOne();
23
if (!$file) {
24
return new Aphront404Response();
25
}
26
27
$secret_key = $request->getURIData('key');
28
if (!$file->validateSecretKey($secret_key)) {
29
return new Aphront403Response();
30
}
31
32
$transform = $request->getURIData('transform');
33
$xform = $this->loadTransform($source_phid, $transform);
34
35
if ($xform) {
36
if ($is_regenerate) {
37
$this->destroyTransform($xform);
38
} else {
39
return $this->buildTransformedFileResponse($xform);
40
}
41
}
42
43
$xforms = PhabricatorFileTransform::getAllTransforms();
44
if (!isset($xforms[$transform])) {
45
return new Aphront404Response();
46
}
47
48
$xform = $xforms[$transform];
49
50
// We're essentially just building a cache here and don't need CSRF
51
// protection.
52
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
53
54
$xformed_file = null;
55
if ($xform->canApplyTransform($file)) {
56
try {
57
$xformed_file = $xforms[$transform]->applyTransform($file);
58
} catch (Exception $ex) {
59
// In normal transform mode, we ignore failures and generate a
60
// default transform below. If we're explicitly regenerating the
61
// thumbnail, rethrow the exception.
62
if ($is_regenerate) {
63
throw $ex;
64
}
65
}
66
}
67
68
if (!$xformed_file) {
69
$xformed_file = $xform->getDefaultTransform($file);
70
}
71
72
if (!$xformed_file) {
73
return new Aphront400Response();
74
}
75
76
$xform = id(new PhabricatorTransformedFile())
77
->setOriginalPHID($source_phid)
78
->setTransform($transform)
79
->setTransformedPHID($xformed_file->getPHID());
80
81
try {
82
$xform->save();
83
} catch (AphrontDuplicateKeyQueryException $ex) {
84
// If we collide when saving, we've raced another endpoint which was
85
// transforming the same file. Just throw our work away and use that
86
// transform instead.
87
$this->destroyTransform($xform);
88
$xform = $this->loadTransform($source_phid, $transform);
89
if (!$xform) {
90
return new Aphront404Response();
91
}
92
}
93
94
return $this->buildTransformedFileResponse($xform);
95
}
96
97
private function buildTransformedFileResponse(
98
PhabricatorTransformedFile $xform) {
99
100
$file = id(new PhabricatorFileQuery())
101
->setViewer(PhabricatorUser::getOmnipotentUser())
102
->withPHIDs(array($xform->getTransformedPHID()))
103
->executeOne();
104
if (!$file) {
105
return new Aphront404Response();
106
}
107
108
// TODO: We could just delegate to the file view controller instead,
109
// which would save the client a roundtrip, but is slightly more complex.
110
111
return $file->getRedirectResponse();
112
}
113
114
private function destroyTransform(PhabricatorTransformedFile $xform) {
115
$engine = new PhabricatorDestructionEngine();
116
$file = id(new PhabricatorFileQuery())
117
->setViewer($engine->getViewer())
118
->withPHIDs(array($xform->getTransformedPHID()))
119
->executeOne();
120
121
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
122
123
if (!$file) {
124
if ($xform->getID()) {
125
$xform->delete();
126
}
127
} else {
128
$engine->destroyObject($file);
129
}
130
131
unset($unguarded);
132
}
133
134
private function loadTransform($source_phid, $transform) {
135
return id(new PhabricatorTransformedFile())->loadOneWhere(
136
'originalPHID = %s AND transform = %s',
137
$source_phid,
138
$transform);
139
}
140
141
}
142
143