sunnysideup /
silverstripe-downloadtoemail
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. Loading history...
|
|||
| 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 Loading history...
|
|||
| 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.