This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * Page for Email Download |
||
4 | * Easiest changed by extending this page |
||
5 | * and using the hide_ancestor static to hide this page itself. |
||
6 | */ |
||
7 | |||
8 | class EmailDownloadPage extends Page |
||
0 ignored issues
–
show
|
|||
9 | { |
||
10 | |||
11 | /** |
||
12 | * standard SS Variable |
||
13 | */ |
||
14 | private static $description = "Allow the user to download a file through their e-mail."; |
||
15 | |||
16 | /** |
||
17 | * standard SS Variable |
||
18 | */ |
||
19 | private static $icon = "downloadtoemail/images/treeicons/EmailDownloadPage"; |
||
20 | |||
21 | /** |
||
22 | * standard SS Variable |
||
23 | */ |
||
24 | private static $db = array( |
||
25 | "LinkToThirdPartyDownload" => "Varchar(255)", |
||
26 | "TitleOfFile" => "Varchar(50)", |
||
27 | "EmailSubject" => "Varchar(200)", |
||
28 | "NoAccessContent" => "Varchar(255)", |
||
29 | "ValidityInDays" => "Float", |
||
30 | "AllowReRequest" => "Boolean", |
||
31 | "AllowReRequestLabel" => "Varchar(255)", |
||
32 | "DeclineReRequestLabel" => "Varchar(255)", |
||
33 | "ThankYouForRequesting" => "Varchar(255)", |
||
34 | "ThankYouLink" => "Varchar(255)", |
||
35 | "CopyOfAllEmailsToAdmin" => "Boolean" |
||
36 | ); |
||
37 | |||
38 | /** |
||
39 | * standard SS Variable |
||
40 | */ |
||
41 | private static $has_one = array( |
||
42 | "DownloadFile" => "File" |
||
43 | ); |
||
44 | |||
45 | /** |
||
46 | * standard SS Variable |
||
47 | */ |
||
48 | private static $has_many = array( |
||
49 | "EmailsSent" => "EmailDownloadPage_Registration" |
||
50 | ); |
||
51 | |||
52 | /** |
||
53 | * standard SS Variable |
||
54 | */ |
||
55 | private static $defaults = array( |
||
56 | "NoAccessContent" => "Sorry, you do not have access to this file right now. Please request access again.", |
||
57 | "ThankYouForRequesting" => "Thank you for requesting this download, please check your e-mail for more information ...", |
||
58 | "AllowReRequest" => true, |
||
59 | "AllowReRequestLabel" => "Request another copy.", |
||
60 | "DeclineReRequestLabel" => "You have already requested this file and you can not request it again." |
||
61 | ); |
||
62 | |||
63 | /** |
||
64 | * |
||
65 | * @param boolean $includerelations a boolean value to indicate if the labels returned include relation fields |
||
66 | * |
||
67 | */ |
||
68 | public function fieldLabels($includerelations = true) |
||
69 | { |
||
70 | $labels = parent::fieldLabels($includerelations); |
||
71 | $labels["TitleOfFile"] = _t("EmailDownloadPage.TITLEOFFILE", "Title of file"); |
||
72 | $labels["LinkToThirdPartyDownload"] = _t("EmailDownloadPage.LINKTOTHIRDPARTYDOWNLOAD", "Link to third-party download file / page"); |
||
73 | $labels["ValidityInDays"] = _t("EmailDownloadPage.VALIDITYINDAYS", "Validity in days (you can use 0.5 for 12 hours, etc...)"); |
||
74 | $labels["DownloadFile"] = $labels["DownloadFileID"] = _t("EmailDownloadPage.DOWNLOADFILE", "Select file to download"); |
||
75 | $labels["ThankYouForRequesting"] = _t("EmailDownloadPage.THANKYOUFORREQUESTING", "Thank you for requesting message"); |
||
76 | $labels["ThankYouLink"] = _t("EmailDownloadPage.THANKYOULINK", "Thank you link"); |
||
77 | $labels["EmailSubject"] = _t("EmailDownloadPage.EMAILSUBJECT", "E-mail Subject"); |
||
78 | $labels["AllowReRequest"] = _t("EmailDownloadPage.ALLOWREREQUEST", "Allow the user to make more than one request for the file (not strictly enforced) - change and reload to see more options"); |
||
79 | $labels["AllowReRequestLabel"] = _t("EmailDownloadPage.ALLOWREREQUESTLABEL", "Label for requesting another copy"); |
||
80 | $labels["DeclineReRequestLabel"] = _t("EmailDownloadPage.DECLINEREREQUESTLABEL", "Explanation of why the user can not request another copy"); |
||
81 | $labels["NoAccessContent"] = _t("EmailDownloadPage.NOACCESSCONTENT", "Content shown when the user does not have access"); |
||
82 | $labels["EmailsSent"] = _t("EmailDownloadPage.EMAILSSENT", "Downloads requested"); |
||
83 | $labels["CopyOfAllEmailsToAdmin"] = _t("EmailDownloadPage.COPYOFALLEMAILSTOADMIN", "Send a copy of all e-mails to the website administrator "); |
||
84 | return $labels; |
||
85 | } |
||
86 | |||
87 | /** |
||
88 | * standard SS Method |
||
89 | */ |
||
90 | public function getCMSFields() |
||
91 | { |
||
92 | $fields = parent::getCMSFields(); |
||
93 | $labels = $this->fieldLabels(true); |
||
94 | $fieldsToAdd = array( |
||
95 | new TextField("TitleOfFile", $labels["TitleOfFile"]), |
||
96 | $uploadField = new UploadField("DownloadFile", $labels["DownloadFile"]) |
||
97 | ); |
||
98 | |||
99 | |||
100 | if ($this->DownloadFileID) { |
||
101 | $fieldsToAdd = array_merge($fieldsToAdd, array( |
||
102 | new NumericField("ValidityInDays", $label["ValidityInDays"]) |
||
103 | )); |
||
104 | } else { |
||
105 | $fieldsToAdd = array_merge($fieldsToAdd, array( |
||
106 | $linkToThirdPartyDownloadField = new TextField("LinkToThirdPartyDownload", $labels["LinkToThirdPartyDownload"]) |
||
107 | )); |
||
108 | $linkToThirdPartyDownloadField->setRightTitle(_t("EmailDownloadPage.LINKTOTHIRDPARTYDOWNLOAD_RIGHT_TITLE", "Set this to a third-party website link (e.g. dropbox) - e.g. http://www.mycooldownloadpage.com/mydownloadpage/")); |
||
109 | } |
||
110 | $fieldsToAdd = array_merge($fieldsToAdd, array( |
||
111 | new CheckboxField("AllowReRequest", $labels["AllowReRequest"]), |
||
112 | new TextField("EmailSubject", $labels["EmailSubject"]), |
||
113 | new CheckboxField("CopyOfAllEmailsToAdmin", $labels["CopyOfAllEmailsToAdmin"]." (".Email::getAdminEmail().")"), |
||
114 | new TextField("ThankYouForRequesting", $labels["ThankYouForRequesting"]), |
||
115 | new TextField("ThankYouLink", $labels["ThankYouLink"]) |
||
116 | )); |
||
117 | if ($this->AllowReRequest) { |
||
118 | $fieldsToAdd = array_merge($fieldsToAdd, array( |
||
119 | new TextField("AllowReRequestLabel", $labels["AllowReRequestLabel"]), |
||
120 | )); |
||
121 | } else { |
||
122 | $fieldsToAdd = array_merge($fieldsToAdd, array( |
||
123 | new TextField("DeclineReRequestLabel", $labels["DeclineReRequestLabel"]), |
||
124 | )); |
||
125 | } |
||
126 | $fieldsToAdd = array_merge($fieldsToAdd, array( |
||
127 | new TextField("NoAccessContent", $labels["NoAccessContent"]), |
||
128 | $gridField = new GridField("EmailsSent", $labels["EmailsSent"], $this->EmailsSent(), GridFieldConfig_RelationEditor::create()) |
||
129 | )); |
||
130 | $gridField->getConfig()->addComponent(new GridFieldExportButton()); |
||
131 | $fields->addFieldsToTab( |
||
132 | "Root.DownloadToEmail", |
||
133 | $fieldsToAdd |
||
134 | ); |
||
135 | return $fields; |
||
136 | } |
||
137 | } |
||
138 | |||
139 | class EmailDownloadPage_Controller extends Page_Controller |
||
0 ignored issues
–
show
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.
You can fix this by adding a namespace to your class: namespace YourVendor;
class YourClass { }
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries. ![]() |
|||
140 | { |
||
141 | |||
142 | /** |
||
143 | * standard SS Variable |
||
144 | */ |
||
145 | private static $allowed_actions = array( |
||
146 | "DownloadForm", |
||
147 | "dodownload", |
||
148 | "thankyou", |
||
149 | "requestrerequest", |
||
150 | "noaccess" |
||
151 | ); |
||
152 | |||
153 | /** |
||
154 | * Template to be used for sending e-mail. |
||
155 | * @var String |
||
156 | */ |
||
157 | private static $email_template = "DownloadToEmailEmail"; |
||
158 | |||
159 | /** |
||
160 | * Show the download form? |
||
161 | * @var Boolean |
||
162 | */ |
||
163 | protected $showDownloadForm = true; |
||
164 | |||
165 | /** |
||
166 | * Message to user (e.g. you do not have access to this file) |
||
167 | * @var String |
||
168 | */ |
||
169 | protected $feedbackMessage = ""; |
||
170 | |||
171 | /** |
||
172 | * Type of feedback (Good | Bad | Warning) |
||
173 | * @var String |
||
174 | */ |
||
175 | protected $feedbackMessageStyle = ""; |
||
176 | |||
177 | |||
178 | /** |
||
179 | * Standard SS method |
||
180 | */ |
||
181 | public function init() |
||
182 | { |
||
183 | parent::init(); |
||
184 | $this->showDownloadForm = $this->AlreadyRequestedSuccessfully() ? false : true; |
||
185 | } |
||
186 | |||
187 | |||
188 | /** |
||
189 | * |
||
190 | * @return Boolean |
||
191 | */ |
||
192 | public function AlreadyRequestedSuccessfully() |
||
193 | { |
||
194 | return Session::get($this->sessionVarNameForSending()) ? true : false; |
||
195 | } |
||
196 | |||
197 | public function ReRequestLink() |
||
198 | { |
||
199 | return $this->Link("requestrerequest"); |
||
200 | } |
||
201 | |||
202 | /** |
||
203 | * feedback message for user |
||
204 | * @return Varchar |
||
205 | */ |
||
206 | public function ShowDownloadForm() |
||
207 | { |
||
208 | return $this->showDownloadForm; |
||
209 | } |
||
210 | |||
211 | /** |
||
212 | * feedback message for user |
||
213 | * @return Varchar |
||
214 | */ |
||
215 | public function FeedbackMessage() |
||
216 | { |
||
217 | return DBField::create_field('Varchar', $this->feedbackMessage); |
||
218 | } |
||
219 | |||
220 | /** |
||
221 | * feedback message for user |
||
222 | * @return Varchar |
||
223 | */ |
||
224 | public function FeedbackMessageStyle() |
||
225 | { |
||
226 | return DBField::create_field('Varchar', $this->feedbackMessageStyle); |
||
227 | } |
||
228 | |||
229 | /** |
||
230 | * show the download form. |
||
231 | * |
||
232 | * @return Form |
||
233 | */ |
||
234 | public function DownloadForm() |
||
235 | { |
||
236 | Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js'); |
||
237 | Requirements::javascript('downloadtoemail/javascript/DownloadToEmail.js'); |
||
238 | $form = new Form( |
||
239 | $this, |
||
240 | 'DownloadForm', |
||
241 | new FieldList($emailField = new EmailField('EmailDownloadPageEmail', _t("EmailDownloadPage.EMAIL", "enter your e-mail address"))), |
||
242 | new FieldList(new FormAction('sendmail', _t("EmailDownloadPage.REQUEST_ACCESS", "request access"))), |
||
243 | RequiredFields::create(array("EmailDownloadPageEmail")) |
||
244 | ); |
||
245 | return $form; |
||
246 | } |
||
247 | |||
248 | /** |
||
249 | * Sent the e-mail. |
||
250 | * |
||
251 | * @param Array $data |
||
252 | * @param Form $form |
||
253 | */ |
||
254 | public function sendmail($data, $form) |
||
255 | { |
||
256 | $email = Convert::raw2sql($data["EmailDownloadPageEmail"]); |
||
257 | $obj = EmailDownloadPage_Registration::get() |
||
258 | ->filter(array("Email" => $email, "DownloadFileID" => $this->DownloadFileID)) |
||
259 | ->first(); |
||
260 | if (!$obj) { |
||
261 | $obj = new EmailDownloadPage_Registration(); |
||
262 | $obj->Email = $email; |
||
263 | $obj->DownloadFileID = $this->DownloadFileID; |
||
264 | } else { |
||
265 | $obj->Used = false; |
||
266 | } |
||
267 | $obj->EmailDownloadPageID = $this->ID; |
||
268 | $obj->write(); |
||
269 | $adminEmail = Email::getAdminEmail(); |
||
270 | if (!$adminEmail) { |
||
271 | user_error("You need to set an admin email in order to use this page", E_USER_NOTICE); |
||
272 | } |
||
273 | $email = new Email($adminEmail, $data["EmailDownloadPageEmail"], $this->EmailSubject); |
||
274 | if ($this->CopyOfAllEmailsToAdmin) { |
||
275 | $email->setBcc($adminEmail); |
||
276 | } |
||
277 | $email->setTemplate($this->config()->get("email_template")); |
||
278 | // You can call this multiple times or bundle everything into an array, including DataSetObjects |
||
279 | $email->populateTemplate( |
||
280 | new ArrayData( |
||
281 | array( |
||
282 | "EmailSubject" => DBField::create_field('Varchar', $this->EmailSubject), |
||
283 | "TitleOfFile" => DBField::create_field('Varchar', $this->TitleOfFile), |
||
284 | "ValidUntil" => date('Y-M-d', strtotime("+".($this->ValidityInDays * 86400)." seconds")), |
||
285 | "HasLink" => $this->LinkToThirdPartyDownload ? true : false, |
||
286 | "HasFile" => $this->DownloadFileID ? true : false, |
||
287 | "LinkToThirdPartyDownload" => $this->LinkToThirdPartyDownload, |
||
288 | "File" => $this->DownloadFile(), |
||
289 | "DownloadLink" => Director::absoluteURL($this->Link("dodownload/".$obj->ID."/".$obj->Code.'/')), |
||
290 | "FileLocation" => Director::absoluteURL($this->DownloadFile()->Link()) |
||
291 | ) |
||
292 | ) |
||
293 | ); |
||
294 | $outcome = $email->send(); |
||
295 | Session::set($this->sessionVarNameForSending(), $outcome); |
||
296 | $this->redirect($this->Link("thankyou/".($outcome ? "success" : "fail")."/")); |
||
297 | return array(); |
||
298 | } |
||
299 | |||
300 | /** |
||
301 | * Do the download itself. |
||
302 | * URL should be formatted as |
||
303 | * /thankyou/outcome/ |
||
304 | * |
||
305 | * @param HTTPRequest |
||
306 | */ |
||
307 | public function thankyou($request) |
||
308 | { |
||
309 | $outcome = $request->param("ID"); |
||
310 | if ($outcome == "success") { |
||
311 | $this->feedbackMessage = $this->ThankYouForRequesting; |
||
312 | $this->feedbackMessageStyle = "good"; |
||
313 | $this->showDownloadForm = false; |
||
314 | $this->DeclineReRequestLabel = ""; |
||
315 | } else { |
||
316 | $this->feedbackMessage = "E-mail could not be sent."; |
||
317 | $this->feedbackMessageStyle = "bad"; |
||
318 | $this->DeclineReRequestLabel = ""; |
||
319 | } |
||
320 | return array(); |
||
321 | } |
||
322 | |||
323 | /** |
||
324 | * Do the download itself. |
||
325 | * URL should be formatted as |
||
326 | * /dodownload/$ID/$CodeForObject/ |
||
327 | * |
||
328 | * @param HTTPRequest |
||
329 | */ |
||
330 | public function dodownload($request) |
||
331 | { |
||
332 | Session::set($this->sessionVarNameForSending(), true); |
||
333 | $id = intval($request->param("ID")); |
||
334 | $code = Convert::raw2sql($request->param("OtherID")); |
||
335 | if ($id && $code) { |
||
336 | $obj = EmailDownloadPage_Registration::get()->filter( |
||
337 | array( |
||
338 | "ID" => $id, |
||
339 | "Code" => $code, |
||
340 | "Used" => 0 |
||
341 | ) |
||
342 | )->First(); |
||
343 | if ($obj) { |
||
344 | if ($this->ValidityInDays) { |
||
345 | $tsNow = strtotime("NOW"); |
||
346 | $validUntilTs = strtotime($obj->Created." +".(86400 * $this->ValidityInDays)." seconds"); |
||
347 | if ($tsNow > $validUntilTs) { |
||
348 | return $this->redirect($this->Link("noaccess")); |
||
349 | } |
||
350 | } |
||
351 | $obj->DownloadTimes++; |
||
352 | $obj->Used = true; |
||
353 | $obj->write(); |
||
354 | return $this->sendFile($obj->DownloadFile()); |
||
355 | } |
||
356 | } |
||
357 | $this->redirect($this->Link("noaccess")); |
||
358 | } |
||
359 | |||
360 | /** |
||
361 | * |
||
362 | * What happens when the person does not have access. |
||
363 | */ |
||
364 | public function noaccess() |
||
365 | { |
||
366 | $this->feedbackMessage = $this->NoAccessContent; |
||
367 | $this->feedbackMessageStyle = "warning"; |
||
368 | return array(); |
||
369 | } |
||
370 | |||
371 | /** |
||
372 | * |
||
373 | * What happens when the person does not have access. |
||
374 | */ |
||
375 | public function requestrerequest() |
||
376 | { |
||
377 | if ($this->AllowReRequest) { |
||
378 | Session::set($this->sessionVarNameForSending(), false); |
||
379 | Session::clear($this->sessionVarNameForSending()); |
||
380 | $this->redirect($this->Link()); |
||
381 | } else { |
||
382 | $this->redirect($this->Link("noaccess")); |
||
383 | } |
||
384 | return array(); |
||
385 | } |
||
386 | |||
387 | // We calculate the timelimit based on the filesize. Set to 0 to give unlimited timelimit. |
||
388 | // The calculation is: give enough time for the user with x kB/s connection to donwload the entire file. |
||
389 | // E.g. The default 50kB/s equates to 348 minutes per 1GB file. |
||
390 | private static $min_download_bandwidth = 50; // [in kilobytes per second] |
||
391 | |||
392 | /** |
||
393 | * |
||
394 | * COPIED CODE!!!!! |
||
395 | * |
||
396 | * This is copied from here: |
||
397 | * https://github.com/silverstripe-labs/silverstripe-secureassets/blob/master/code/SecureFileController.php |
||
398 | * |
||
399 | * @param File $file |
||
400 | */ |
||
401 | protected function sendFile($file) |
||
402 | { |
||
403 | $path = $file->getFullPath(); |
||
404 | if (SapphireTest::is_running_test()) { |
||
405 | return file_get_contents($path); |
||
406 | } |
||
407 | header('Content-Description: File Transfer'); |
||
408 | // Quotes needed to retain spaces (http://kb.mozillazine.org/Filenames_with_spaces_are_truncated_upon_download) |
||
409 | header('Content-Disposition: inline; filename="' . basename($path) . '"'); |
||
410 | header('Content-Length: ' . $file->getAbsoluteSize()); |
||
411 | header('Content-Type: ' . HTTP::get_mime_type($file->getRelativePath())); |
||
412 | header('Content-Transfer-Encoding: binary'); |
||
413 | // Fixes IE6,7,8 file downloads over HTTPS bug (http://support.microsoft.com/kb/812935) |
||
414 | header('Pragma: '); |
||
415 | if ($this->config()->min_download_bandwidth) { |
||
416 | // Allow the download to last long enough to allow full download with min_download_bandwidth connection. |
||
417 | increase_time_limit_to((int)(filesize($path)/($this->config()->min_download_bandwidth*1024))); |
||
418 | } else { |
||
419 | // Remove the timelimit. |
||
420 | increase_time_limit_to(0); |
||
421 | } |
||
422 | // Clear PHP buffer, otherwise the script will try to allocate memory for entire file. |
||
423 | while (ob_get_level() > 0) { |
||
424 | ob_end_flush(); |
||
425 | } |
||
426 | // Prevent blocking of the session file by PHP. Without this the user can't visit another page of the same |
||
427 | // website during download (see http://konrness.com/php5/how-to-prevent-blocking-php-requests/) |
||
428 | session_write_close(); |
||
429 | readfile($path); |
||
430 | die(); |
||
0 ignored issues
–
show
The method
sendFile() contains an exit expression.
An exit expression should only be used in rare cases. For example, if you write a short command line script. In most cases however, using an ![]() |
|||
431 | } |
||
432 | |||
433 | /** |
||
434 | * |
||
435 | * @return String |
||
436 | */ |
||
437 | protected function sessionVarNameForSending() |
||
438 | { |
||
439 | return "EmailDownloadPage_Controller_".$this->ID."_Sent"; |
||
440 | } |
||
441 | } |
||
442 |
You can fix this by adding a namespace to your class:
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.