/** * Downloads a file and cleans up old temporary assets */ public function actionDownloadFile() { // Clean up temp assets files that are more than a day old $fileResults = array(); $files = IOHelper::getFiles(craft()->path->getTempPath(), true); foreach ($files as $file) { $lastModifiedTime = IOHelper::getLastTimeModified($file, true); if (substr(IOHelper::getFileName($file, false, true), 0, 6) === "assets" && DateTimeHelper::currentTimeStamp() - $lastModifiedTime->getTimestamp() >= 86400) { IOHelper::deleteFile($file); } } // Sort out the file we want to download $id = craft()->request->getParam('id'); $criteria = craft()->elements->getCriteria(ElementType::Asset); $criteria->id = $id; $asset = $criteria->first(); if ($asset) { // Get a local copy of the file $sourceType = craft()->assetSources->getSourceTypeById($asset->sourceId); $localCopy = $sourceType->getLocalCopy($asset); // Send it to the browser craft()->request->sendFile($asset->filename, IOHelper::getFileContents($localCopy), array('forceDownload' => true)); craft()->end(); } }
/** * Calculate the modified time of asset * * @return DateTime */ public function getLastTimeModified() { if ($this->_lastTimeModified === null) { $this->_lastTimeModified = IOHelper::getLastTimeModified($this->filenamePath); if ($this->_lastTimeModified === false) { throw new Exception('Minimee could not determine modification time of local asset: ' . $this->filenamePath); } } return $this->_lastTimeModified; }
/** * Returns whether the cached template is still up-to-date with the latest template. * * @param string $name The template name, or a StringTemplate object. * @param timestamp $time The last modification time of the cached template * @return bool */ public function isFresh($name, $time) { // If this is a CP request and a DB update is needed, force a recompile. if (craft()->request->isCpRequest() && craft()->updates->isCraftDbUpdateNeeded()) { return false; } if (is_string($name)) { $sourceModifiedTime = IOHelper::getLastTimeModified(craft()->templates->findTemplate($name)); return $sourceModifiedTime->getTimestamp() <= $time; } else { return false; } }
/** * Sends a file to the user. * * We’re overriding this from {@link \CHttpRequest::sendFile()} so we can have more control over the headers. * * @param string $path The path to the file on the server. * @param string $content The contents of the file. * @param array|null $options An array of optional options. Possible keys include 'forceDownload', 'mimeType', * and 'cache'. * @param bool|null $terminate Whether the request should be terminated after the file has been sent. * Defaults to `true`. * * @throws HttpException * @return null */ public function sendFile($path, $content, $options = array(), $terminate = true) { $fileName = IOHelper::getFileName($path, true); // Clear the output buffer to prevent corrupt downloads. Need to check the OB status first, or else some PHP // versions will throw an E_NOTICE since we have a custom error handler // (http://pear.php.net/bugs/bug.php?id=9670) if (ob_get_length() !== false) { // If zlib.output_compression is enabled, then ob_clean() will corrupt the results of output buffering. // ob_end_clean is what we want. ob_end_clean(); } // Default to disposition to 'download' $forceDownload = !isset($options['forceDownload']) || $options['forceDownload']; if ($forceDownload) { HeaderHelper::setDownload($fileName); } if (empty($options['mimeType'])) { if (($options['mimeType'] = \CFileHelper::getMimeTypeByExtension($fileName)) === null) { $options['mimeType'] = 'text/plain'; } } HeaderHelper::setHeader(array('Content-Type' => $options['mimeType'] . '; charset=utf-8')); $fileSize = mb_strlen($content, '8bit'); $contentStart = 0; $contentEnd = $fileSize - 1; $httpVersion = $this->getHttpVersion(); if (isset($_SERVER['HTTP_RANGE'])) { HeaderHelper::setHeader(array('Accept-Ranges' => 'bytes')); // Client sent us a multibyte range, can not hold this one for now if (mb_strpos($_SERVER['HTTP_RANGE'], ',') !== false) { HeaderHelper::setHeader(array('Content-Range' => 'bytes ' . $contentStart - $contentEnd / $fileSize)); throw new HttpException(416, 'Requested Range Not Satisfiable'); } $range = str_replace('bytes=', '', $_SERVER['HTTP_RANGE']); // range requests starts from "-", so it means that data must be dumped the end point. if ($range[0] === '-') { $contentStart = $fileSize - mb_substr($range, 1); } else { $range = explode('-', $range); $contentStart = $range[0]; // check if the last-byte-pos presents in header if (isset($range[1]) && is_numeric($range[1])) { $contentEnd = $range[1]; } } // Check the range and make sure it's treated according to the specs. // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html // End bytes can not be larger than $end. $contentEnd = $contentEnd > $fileSize ? $fileSize - 1 : $contentEnd; // Validate the requested range and return an error if it's not correct. $wrongContentStart = $contentStart > $contentEnd || $contentStart > $fileSize - 1 || $contentStart < 0; if ($wrongContentStart) { HeaderHelper::setHeader(array('Content-Range' => 'bytes ' . $contentStart - $contentEnd / $fileSize)); throw new HttpException(416, 'Requested Range Not Satisfiable'); } HeaderHelper::setHeader("HTTP/{$httpVersion} 206 Partial Content"); HeaderHelper::setHeader(array('Content-Range' => 'bytes ' . $contentStart - $contentEnd / $fileSize)); } else { HeaderHelper::setHeader("HTTP/{$httpVersion} 200 OK"); } // Calculate new content length $length = $contentEnd - $contentStart + 1; if (!empty($options['cache'])) { $cacheTime = 31536000; // 1 year HeaderHelper::setHeader(array('Expires' => gmdate('D, d M Y H:i:s', time() + $cacheTime) . ' GMT')); HeaderHelper::setHeader(array('Pragma' => 'cache')); HeaderHelper::setHeader(array('Cache-Control' => 'max-age=' . $cacheTime)); $modifiedTime = IOHelper::getLastTimeModified($path); HeaderHelper::setHeader(array('Last-Modified' => gmdate("D, d M Y H:i:s", $modifiedTime->getTimestamp()) . ' GMT')); } else { if (!$forceDownload) { HeaderHelper::setNoCache(); } else { // Fixes a bug in IE 6, 7 and 8 when trying to force download a file over SSL: // https://stackoverflow.com/questions/1218925/php-script-to-download-file-not-working-in-ie HeaderHelper::setHeader(array('Pragma' => '', 'Cache-Control' => '')); } } if ($options['mimeType'] == 'application/x-javascript' || $options['mimeType'] == 'text/css') { HeaderHelper::setHeader(array('Vary' => 'Accept-Encoding')); } if (!ob_get_length()) { HeaderHelper::setLength($length); } $content = mb_substr($content, $contentStart, $length); if ($terminate) { // Clean up the application first because the file downloading could take long time which may cause timeout // of some resources (such as DB connection) ob_start(); Craft::app()->end(0, false); ob_end_clean(); echo $content; exit(0); } else { echo $content; } }
/** * @return mixed */ public function getLastTimeModified() { if (!$this->_lastTimeModified) { $this->_lastTimeModified = IOHelper::getLastTimeModified($this->getRealPath()); } return $this->_lastTimeModified; }
/** * Upload a file. * * @param AssetFolderModel $folder * @return object * @throws Exception */ public function uploadFile($folder) { // Upload the file and drop it in the temporary folder $uploader = new \qqFileUploader(); // Make sure a file was uploaded if (!$uploader->file) { throw new Exception(Craft::t('No file was uploaded')); } $size = $uploader->file->getSize(); // Make sure the file isn't empty if (!$size) { throw new Exception(Craft::t('Uploaded file was empty')); } $fileName = IOHelper::cleanFilename($uploader->file->getName()); // Save the file to a temp location and pass this on to the source type implementation $filePath = AssetsHelper::getTempFilePath(IOHelper::getExtension($fileName)); $uploader->file->save($filePath); // We hate Javascript and PHP in our image files. if (IOHelper::getFileKind(IOHelper::getExtension($filePath)) == 'image') { craft()->images->cleanImage($filePath); } $response = $this->_insertFileInFolder($folder, $filePath, $fileName); // Naming conflict. create a new file and ask the user what to do with it if ($response->isConflict()) { $newFileName = $this->_getNameReplacement($folder, $fileName); $conflictResponse = $response; $response = $this->_insertFileInFolder($folder, $filePath, $newFileName); } if ($response->isSuccess()) { $filename = IOHelper::getFileName($response->getDataItem('filePath')); $fileModel = new AssetFileModel(); $fileModel->sourceId = $this->model->id; $fileModel->folderId = $folder->id; $fileModel->filename = IOHelper::getFileName($filename); $fileModel->kind = IOHelper::getFileKind(IOHelper::getExtension($filename)); $fileModel->size = filesize($filePath); $fileModel->dateModified = IOHelper::getLastTimeModified($filePath); if ($fileModel->kind == 'image') { list($width, $height) = getimagesize($filePath); $fileModel->width = $width; $fileModel->height = $height; } craft()->assets->storeFile($fileModel); if (!$this->isSourceLocal() && $fileModel->kind == 'image') { // Store copy locally for all sorts of operations. IOHelper::copyFile($filePath, craft()->path->getAssetsImageSourcePath() . $fileModel->id . '.' . IOHelper::getExtension($fileModel->filename)); } // Check if we stored a conflict response originally - send that back then. if (isset($conflictResponse)) { $response = $conflictResponse->setDataItem('additionalInfo', $folder->id . ':' . $fileModel->id)->setDataItem('newFileId', $fileModel->id); } $response->setDataItem('fileId', $fileModel->id); } IOHelper::deleteFile($filePath); // Prevent sensitive information leak. Just in case. $response->deleteDataItem('filePath'); return $response; }
/** * Insert a file into a folder by it's local path. * * @param string $localFilePath The local file path of the file to insert. * @param AssetFolderModel $folder The assetFolderModel where the file should be uploaded to. * @param string $filename The name of the file to insert. * @param bool $preventConflicts If set to true, will ensure that a conflict is not encountered by * checking the file name prior insertion. * * @return AssetOperationResponseModel */ public function insertFileByPath($localFilePath, AssetFolderModel $folder, $filename, $preventConflicts = false) { // Fire an 'onBeforeUploadAsset' event $event = new Event($this, array('path' => $localFilePath, 'folder' => $folder, 'filename' => $filename)); craft()->assets->onBeforeUploadAsset($event); if ($event->performAction) { // We hate Javascript and PHP in our image files. if (IOHelper::getFileKind(IOHelper::getExtension($localFilePath)) == 'image' && ImageHelper::isImageManipulatable(IOHelper::getExtension($localFilePath)) && IOHelper::getExtension($localFilePath) != 'svg') { craft()->images->cleanImage($localFilePath); } $mobileUpload = false; if (IOHelper::getFileName($filename, false) == "image" && craft()->request->isMobileBrowser(true)) { $mobileUpload = true; $date = DateTimeHelper::currentUTCDateTime(); $filename = "image_" . $date->format('Ymd_His') . "." . IOHelper::getExtension($filename); } if ($preventConflicts) { $newFileName = $this->getNameReplacementInFolder($folder, $filename); $response = $this->insertFileInFolder($folder, $localFilePath, $newFileName); } else { $response = $this->insertFileInFolder($folder, $localFilePath, $filename); // Naming conflict. create a new file and ask the user what to do with it if ($response->isConflict()) { $newFileName = $this->getNameReplacementInFolder($folder, $filename); $conflictResponse = $response; $response = $this->insertFileInFolder($folder, $localFilePath, $newFileName); } } if ($response->isSuccess()) { $fileModel = new AssetFileModel(); $title = $fileModel->generateAttributeLabel(IOHelper::getFileName($filename, false)); // If there were double spaces, it's because the filename had a space followed by a // capital letter. We convert the space to a dash, but Yii thinks it's a new "word" // and adds another space. $fileModel->getContent()->title = str_replace(' ', ' ', $title); $filename = IOHelper::getFileName($response->getDataItem('filePath')); $fileModel->filename = IOHelper::getFileName($filename); $fileModel->sourceId = $this->model->id; $fileModel->folderId = $folder->id; $fileModel->kind = IOHelper::getFileKind(IOHelper::getExtension($filename)); $fileModel->size = filesize($localFilePath); $fileModel->dateModified = IOHelper::getLastTimeModified($localFilePath); if ($fileModel->kind == 'image') { list($width, $height) = ImageHelper::getImageSize($localFilePath); $fileModel->width = $width; $fileModel->height = $height; } if ($mobileUpload) { $fileModel->getContent()->title = Craft::t('Mobile Upload'); } craft()->assets->storeFile($fileModel); if (!$this->isSourceLocal() && $fileModel->kind == 'image') { craft()->assetTransforms->storeLocalSource($localFilePath, craft()->path->getAssetsImageSourcePath() . $fileModel->id . '.' . IOHelper::getExtension($fileModel->filename)); } // Check if we stored a conflict response originally - send that back then. if (isset($conflictResponse)) { $response = $conflictResponse; } $response->setDataItem('fileId', $fileModel->id); } } else { $response = new AssetOperationResponseModel(); $response->setError(Craft::t('The file upload was cancelled.')); } return $response; }
/** * Returns a resource URL. * * @param string $path * @param array|string|null $params * @param string|null $protocol The protocol to use (e.g. http, https). If empty, the protocol used for the * current request will be used. * * @return string */ public static function getResourceUrl($path = '', $params = null, $protocol = '') { $path = trim($path, '/'); if ($path) { // If we've served this resource before, we should have a cached copy of the server path already. Use that // to get its timestamp, and add timestamp to the resource URL so ResourcesService sends it with // a Pragma: Cache header. $dateParam = craft()->resources->dateParam; if (!isset($params[$dateParam])) { $realPath = craft()->resources->getCachedResourcePath($path); if ($realPath) { if (!is_array($params)) { $params = array($params); } $timeModified = IOHelper::getLastTimeModified($realPath); $params[$dateParam] = $timeModified->getTimestamp(); } else { // Just set a random query string param on there, so even if the browser decides to cache it, // the next time this happens, the cache won't be used. // Use a consistent param for all resource requests with uncached paths, in case the same resource // URL is requested multiple times in the same request if (!isset(static::$_x)) { static::$_x = StringHelper::randomString(9); } $params['x'] = static::$_x; } } } return static::getUrl(craft()->config->getResourceTrigger() . '/' . $path, $params, $protocol); }
/** * Returns a resource URL. * * @static * @param string $path * @param array|string|null $params * @param string|null $protocol protocol to use (e.g. http, https). If empty, the protocol used for the current request will be used. * @return string */ public static function getResourceUrl($path = '', $params = null, $protocol = '') { $path = $origPath = trim($path, '/'); $path = craft()->config->get('resourceTrigger') . '/' . $path; // Add timestamp to the resource URL for caching, if Craft is not operating in dev mode if ($origPath && !craft()->config->get('devMode')) { $realPath = craft()->resources->getResourcePath($origPath); if ($realPath) { if (!is_array($params)) { $params = array($params); } $dateParam = craft()->resources->dateParam; $timeModified = IOHelper::getLastTimeModified($realPath); $params[$dateParam] = $timeModified->getTimestamp(); } } return static::getUrl($path, $params, $protocol); }
public function actionSaveFormEntry() { $ajax = false; $redirect = false; $formBuilderHandle = craft()->request->getPost('formHandle'); if (!$formBuilderHandle) { throw new HttpException(404); } $form = craft()->formBuilder_entries->getFormByHandle($formBuilderHandle); if (!$form) { throw new HttpException(404); } $ajaxSubmit = $form->ajaxSubmit; $formRedirect = $form->successPageRedirect; $formRedirectUrl = $form->redirectUrl; if ($ajaxSubmit) { $ajax = true; $this->requirePostRequest(); $this->requireAjaxRequest(); } else { $this->requirePostRequest(); } $data = craft()->request->getPost(); $postData = $this->_filterPostKeys($data); $formBuilderEntry = new FormBuilder_EntryModel(); $fileupload = true; $validExtension = false; if ($form->hasFileUploads) { if (isset(array_values($_FILES)[0])) { $filename = array_values($_FILES)[0]['name']; $file = array_values($_FILES)[0]['tmp_name']; $extension = IOHelper::getFileKind(IOHelper::getExtension($filename)); if (!in_array($extension, $this->valid_extensions)) { $fileupload = false; $validExtension = false; } else { $validExtension = true; } if ($validExtension) { // Create formbuilder directory inside craft/storage if one doesn't exist $storagePath = craft()->path->getStoragePath(); $myStoragePath = $storagePath . 'formbuilder/'; IOHelper::ensureFolderExists($myStoragePath); $uploadDir = $myStoragePath; // Rename each file with unique name $uniqe_filename = uniqid() . '-' . $filename; foreach ($_FILES as $key => $value) { $fileUploadHandle = $key; } $postData[$fileUploadHandle] = $uniqe_filename; } } } $formBuilderEntry->formId = $form->id; $formBuilderEntry->title = $form->name; $formBuilderEntry->data = $postData; // Use reCaptcha $useCaptcha = $form->useReCaptcha; if ($useCaptcha && !DEV_MODE) { $captchaPlugin = craft()->plugins->getPlugin('recaptcha'); if ($captchaPlugin && $captchaPlugin->isEnabled) { $captcha = craft()->request->getPost('g-recaptcha-response'); $verified = craft()->recaptcha_verify->verify($captcha); } else { $verified = false; } } else { $verified = true; } // Save Form Entry if ($verified && $fileupload && craft()->formBuilder_entries->saveFormEntry($formBuilderEntry)) { // Save Uploaded File if ($validExtension) { if (move_uploaded_file($file, $uploadDir . $uniqe_filename)) { IOHelper::deleteFile($file); $file = $uploadDir . $uniqe_filename; $fileModel = new AssetFileModel(); $fileModel->sourceId = $form->uploadSource; $fileModel->folderId = $this->assetFolderId; $fileModel->filename = IOHelper::getFileName($uniqe_filename); $fileModel->originalName = IOHelper::getFileName($filename); $fileModel->kind = IOHelper::getFileKind(IOHelper::getExtension($uniqe_filename)); $fileModel->size = filesize($file); $fileModel->dateModified = IOHelper::getLastTimeModified($file); if ($fileModel->kind == 'image') { list($width, $height) = ImageHelper::getImageSize($file); $fileModel->width = $width; $fileModel->height = $height; } craft()->assets->storeFile($fileModel); } else { $fileupload = false; } } // Valid extension if ($form->notifyFormAdmin && $form->toEmail != '') { $this->_sendEmailNotification($formBuilderEntry, $form); } if ($form->notifyRegistrant && $form->notificationFieldHandleName != '') { $emailField = craft()->fields->getFieldByHandle($form->notificationFieldHandleName); $submitterEmail = $formBuilderEntry->data[$emailField->handle]; $this->_sendRegistrantEmailNotification($formBuilderEntry, $form, $submitterEmail); } if (!empty($form->successMessage)) { $successMessage = $form->successMessage; } else { $successMessage = Craft::t('Thank you, we have received your submission and we\'ll be in touch shortly.'); } craft()->userSession->setFlash('success', $successMessage); if ($ajax) { $this->returnJson(['success' => true, 'message' => $successMessage]); } else { if ($formRedirect) { $this->redirect($formRedirectUrl); } } } else { if (!$verified) { if (!$captchaPlugin) { craft()->userSession->setFlash('error', 'Please enable reCaptcha plugin!'); $this->redirectToPostedUrl(); } craft()->userSession->setFlash('error', 'Please check captcha!'); $this->redirectToPostedUrl(); } if (!empty($form->errorMessage)) { $errorMessage = $form->errorMessage; } else { $errorMessage = Craft::t('We\'re sorry, but something has gone wrong.'); } if ($ajax) { $this->returnJson(['error' => true, 'message' => $errorMessage]); } else { if ($formRedirect) { $this->redirectToPostedUrl(); } else { craft()->userSession->setFlash('error', $errorMessage); } } } }
/** * Submit Entry * */ public function actionSubmitEntry() { $this->requirePostRequest(); // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // VARIABLES // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ $files = ''; $ajax = false; $passedValidation = true; $validationErrors = []; $submissionErrorMessage = []; $customSuccessMessage = ''; $customErrorMessage = ''; // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // FORM // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ $form = craft()->formBuilder2_entry->getFormByHandle(craft()->request->getPost('formHandle')); // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // FORM SUBMISSION // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ $formFields = $form->fieldLayout->getFieldLayout()->getFields(); // Get all form fields $submission = craft()->request->getPost(); // Get all values from the submitted form $submissionData = $this->filterSubmissionKeys($submission); // Fillter out unused submission data // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // FORM ATTRIBUTES // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ $attributes = $form->getAttributes(); $formSettings = $attributes['formSettings']; $spamProtectionSettings = $attributes['spamProtectionSettings']; $messageSettings = $attributes['messageSettings']; $notificationSettings = $attributes['notificationSettings']; // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // FORM SETTINGS ||| (1) Custom Redirect, (2) File Uploads, (3) Ajax Submissions // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // (1) Custom Redirect if ($formSettings['formRedirect']['customRedirect'] != '') { $redirectUrl = $formSettings['formRedirect']['customRedirectUrl']; } // (2) File Uploads if ($formSettings['hasFileUploads'] == '1') { foreach ($formFields as $key => $value) { $field = $value->getField(); switch ($field->type) { case 'Assets': foreach ($_FILES as $key => $value) { if (!$value['tmp_name'] == '') { $fileModel = new AssetFileModel(); $folderId = $field->settings['singleUploadLocationSource'][0]; $sourceId = $field->settings['singleUploadLocationSource'][0]; $fileModel->originalName = $value['tmp_name']; $fileModel->sourceId = $sourceId; $fileModel->folderId = $folderId; $fileModel->filename = IOHelper::getFileName($value['name']); $fileModel->kind = IOHelper::getFileKind(IOHelper::getExtension($value['name'])); $fileModel->size = filesize($value['tmp_name']); if ($value['tmp_name']) { $fileModel->dateModified = IOHelper::getLastTimeModified($value['tmp_name']); } if ($fileModel->kind == 'image') { list($width, $height) = ImageHelper::getImageSize($value['tmp_name']); $fileModel->width = $width; $fileModel->height = $height; } $files[$key] = $fileModel; } } break; } } } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // FORM CUSTOM MESSAGES ||| (1) Success Message (2) Error Message // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // (1) Success Message $customSuccessMessage = $messageSettings['successMessage'] ? $messageSettings['successMessage'] : Craft::t('Submission was successful.'); // (2) Error Message $customErrorMessage = $messageSettings['errorMessage'] ? $messageSettings['errorMessage'] : Craft::t('There was a problem with your submission.'); // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // (3) Ajax Submissions if ($formSettings['ajaxSubmit'] == '1') { $this->requireAjaxRequest(); $ajax = true; } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // FORM SPAM PROTECTION ||| (1) Timed Method (2) Honeypot Method // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // (1) Timed Method if ($spamProtectionSettings['spamTimeMethod'] == '1') { $formSubmissionTime = (int) craft()->request->getPost('spamTimeMethod'); $submissionDuration = time() - $formSubmissionTime; $allowedTime = (int) $spamProtectionSettings['spamTimeMethodTime']; if ($submissionDuration < $allowedTime) { if ($ajax) { $this->returnJson(['validationErrors' => [Craft::t('You submitted too fast, you are robot!')], 'customErrorMessage' => $customErrorMessage]); } else { $spamTimedMethod = false; $submissionErrorMessage[] = Craft::t('You submitted too fast, you are robot!'); } } else { $spamTimedMethod = true; } } else { $spamTimedMethod = true; } // (2) Honeypot Method if ($spamProtectionSettings['spamHoneypotMethod'] == '1') { $honeypotField = craft()->request->getPost('email-address-new'); if ($honeypotField != '') { if ($ajax) { $this->returnJson(['validationErrors' => [Craft::t('You tried the honey, you are robot bear!')], 'customErrorMessage' => $customErrorMessage]); } else { $spamHoneypotMethod = false; $submissionErrorMessage[] = Craft::t('You tried the honey, you are robot bear!'); } } else { $spamHoneypotMethod = true; } } else { $spamHoneypotMethod = true; } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // NEW FORM MODEL // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ $submissionEntry = new FormBuilder2_EntryModel(); $submissionEntry->formId = $form->id; $submissionEntry->title = $form->name; $submissionEntry->files = $files; $submissionEntry->submission = $submissionData; // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // FAILED SUBMISSION REDIRECT W/MESSAGES (Spam Protection) // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if ($submissionErrorMessage) { craft()->userSession->setFlash('error', $customErrorMessage); craft()->urlManager->setRouteVariables(array('errors' => $submissionErrorMessage)); } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // VALIDATE SUBMISSION DATA // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ $validation = craft()->formBuilder2_entry->validateEntry($form, $submissionData); // if ($validation != '') { if (!empty($validation)) { if ($ajax) { $this->returnJson(['passedValidation' => false, 'validationErrors' => $validation, 'customErrorMessage' => $customErrorMessage]); } else { craft()->userSession->setFlash('error', $customErrorMessage); $passedValidation = false; return craft()->urlManager->setRouteVariables(['value' => $submissionData, 'errors' => $validation]); } } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // PROCESS SUBMISSION ENTRY // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if (!$submissionErrorMessage && $passedValidation && $spamTimedMethod && $spamHoneypotMethod) { $submissionResponseId = craft()->formBuilder2_entry->processSubmissionEntry($submissionEntry); if ($submissionResponseId) { // Notify Admin of Submission if ($notificationSettings['notifySubmission'] == '1') { $this->notifyAdminOfSubmission($submissionResponseId, $form); } // Successful Submission Messages if ($ajax) { $this->returnJson(['success' => true, 'customSuccessMessage' => $customSuccessMessage]); } else { craft()->userSession->setFlash('success', $customSuccessMessage); if ($formSettings['formRedirect']['customRedirect'] != '') { $this->redirect($redirectUrl); } else { $this->redirectToPostedUrl(); } } } else { // Submission Error Messages if ($ajax) { $this->returnJson(['error' => true, 'customErrorMessage' => $customErrorMessage]); } else { craft()->userSession->setFlash('error', $customErrorMessage); return craft()->urlManager->setRouteVariables(['value' => $submissionData, 'errors' => $validation]); } } } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ }
/** * @inheritDoc BaseAssetSourceType::processIndex() * * @param string $sessionId * @param int $offset * * @return mixed */ public function processIndex($sessionId, $offset) { $indexEntryModel = craft()->assetIndexing->getIndexEntry($this->model->id, $sessionId, $offset); if (empty($indexEntryModel)) { return false; } // Make sure we have a trailing slash. Some people love to skip those. $uploadPath = $this->getSourceFileSystemPath(); $file = $indexEntryModel->uri; // This is the part of the path that actually matters $uriPath = mb_substr($file, mb_strlen($uploadPath)); $fileModel = $this->indexFile($uriPath); if ($fileModel) { craft()->assetIndexing->updateIndexEntryRecordId($indexEntryModel->id, $fileModel->id); $fileModel->size = $indexEntryModel->size; $fileModel->dateModified = IOHelper::getLastTimeModified($indexEntryModel->uri); if ($fileModel->kind == 'image') { list($width, $height) = ImageHelper::getImageSize($indexEntryModel->uri); $fileModel->width = $width; $fileModel->height = $height; } craft()->assets->storeFile($fileModel); return $fileModel->id; } return false; }
/** * Get paths for an external file (really external, or on an external source type) * * @param $image * @throws Exception */ private function _getPathsForUrl($image) { $urlParts = parse_url($image); $pathParts = pathinfo($urlParts['path']); $hashRemoteUrl = craft()->imager->getSetting('hashRemoteUrl'); if ($hashRemoteUrl) { if (is_string($hashRemoteUrl) && $hashRemoteUrl == 'host') { $parsedDirname = substr(md5($urlParts['host']), 0, 10) . $pathParts['dirname']; } else { $parsedDirname = md5($urlParts['host'] . $pathParts['dirname']); } } else { $parsedDirname = str_replace('.', '_', $urlParts['host']) . $pathParts['dirname']; } $this->sourcePath = craft()->path->getRuntimePath() . 'imager/' . $parsedDirname . '/'; $this->targetPath = craft()->imager->getSetting('imagerSystemPath') . $parsedDirname . '/'; $this->targetUrl = craft()->imager->getSetting('imagerUrl') . $parsedDirname . '/'; $this->sourceFilename = $this->targetFilename = $pathParts['basename']; // check if the temp path for remote files exists or can be created. if (!IOHelper::getRealPath($this->sourcePath)) { IOHelper::createFolder($this->sourcePath, craft()->config->get('defaultFolderPermissions'), true); if (!IOHelper::getRealPath($this->sourcePath)) { throw new Exception(Craft::t('Temp folder “{sourcePath}” does not exist and could not be created', array('sourcePath' => $this->sourcePath))); } } // check if the file is already downloaded if (!IOHelper::fileExists($this->sourcePath . $this->sourceFilename) || IOHelper::getLastTimeModified($this->sourcePath . $this->sourceFilename)->format('U') + craft()->imager->getSetting('cacheDurationRemoteFiles') < time()) { $this->_downloadFile($this->sourcePath . $this->sourceFilename, $image); if (!IOHelper::fileExists($this->sourcePath . $this->sourceFilename)) { throw new Exception(Craft::t('File could not be downloaded and saved to “{sourcePath}”', array('sourcePath' => $this->sourcePath))); } } }
/** * @return String */ protected function makeUrlToCacheFilename() { if ($this->settings->useResourceCache()) { $path = '/' . self::ResourceTrigger . '/' . $this->makeCacheFilename(); $dateParam = craft()->resources->dateParam; $params[$dateParam] = IOHelper::getLastTimeModified($this->makePathToCacheFilename())->getTimestamp(); return UrlHelper::getUrl(craft()->config->getResourceTrigger() . $path, $params); } return $this->settings->cacheUrl . $this->makeCacheFilename(); }
private function _updateAsset($asset, $image, $path) { // Update our model $asset->size = IOHelper::getFileSize($path); $asset->width = $image->getWidth(); $asset->height = $image->getHeight(); // Then, make sure we update the asset info as stored in the database $fileRecord = AssetFileRecord::model()->findById($asset->id); $fileRecord->size = $asset->size; $fileRecord->width = $asset->width; $fileRecord->height = $asset->height; $fileRecord->dateModified = IOHelper::getLastTimeModified($path); $fileRecord->save(false); }
/** * Submit Entry * */ public function actionSubmitEntry() { $form = craft()->formBuilder2_entry->getFormByHandle(craft()->request->getPost('formHandle')); // Set Up Form Submission $formFields = $form->fieldLayout->getFieldLayout()->getFields(); $submission = craft()->request->getPost(); $submissionData = $this->filterSubmissionKeys($submission); // Defaults $attributes = $form->getAttributes(); $formSettings = $attributes['formSettings']; $spamProtectionSettings = $attributes['spamProtectionSettings']; $messageSettings = $attributes['messageSettings']; $notificationSettings = $attributes['notificationSettings']; $files = ''; $errorMessage = []; // Prepare submissionEntry for processing $submissionEntry = new FormBuilder2_EntryModel(); // Using Ajax if ($formSettings['ajaxSubmit'] == '1') { $this->requireAjaxRequest(); } else { $this->requirePostRequest(); } // Custom Redirect if ($formSettings['formRedirect']['customRedirect'] != '') { $redirectUrl = $formSettings['formRedirect']['customRedirectUrl']; } // Spam Protection | Timed Method if ($spamProtectionSettings['spamTimeMethod'] == '1') { $formSubmissionTime = (int) craft()->request->getPost('spamTimeMethod'); $submissionDuration = time() - $formSubmissionTime; $allowedTime = (int) $spamProtectionSettings['spamTimeMethodTime']; if ($submissionDuration < $allowedTime) { $spamMethodOne = false; $errorMessage[] = Craft::t('You submitted too fast, you are robot!'); } else { $spamMethodOne = true; } } else { $spamMethodOne = true; } // Spam Protection | Honeypot Method if ($spamProtectionSettings['spamHoneypotMethod'] == '1') { $honeypotField = craft()->request->getPost('email-address-new'); if ($honeypotField != '') { $spamMethodTwo = false; $errorMessage[] = Craft::t('You tried the honey, you are robot bear!'); } else { $spamMethodTwo = true; } } else { $spamMethodTwo = true; } // Validate Required Fields $validateRequired = craft()->formBuilder2_entry->validateEntry($form, $submissionData); // File Uploads if ($formSettings['hasFileUploads'] == '1') { foreach ($formFields as $key => $value) { $field = $value->getField(); switch ($field->type) { case 'Assets': foreach ($_FILES as $key => $value) { if (!$value['tmp_name'] == '') { $fileModel = new AssetFileModel(); $folderId = $field->settings['singleUploadLocationSource'][0]; $sourceId = $field->settings['singleUploadLocationSource'][0]; $fileModel->originalName = $value['tmp_name']; $fileModel->sourceId = $sourceId; $fileModel->folderId = $folderId; $fileModel->filename = IOHelper::getFileName($value['name']); $fileModel->kind = IOHelper::getFileKind(IOHelper::getExtension($value['name'])); $fileModel->size = filesize($value['tmp_name']); if ($value['tmp_name']) { $fileModel->dateModified = IOHelper::getLastTimeModified($value['tmp_name']); } if ($fileModel->kind == 'image') { list($width, $height) = ImageHelper::getImageSize($value['tmp_name']); $fileModel->width = $width; $fileModel->height = $height; } $files[$key] = $fileModel; } } break; } } } $submissionEntry->formId = $form->id; $submissionEntry->title = $form->name; $submissionEntry->files = $files; $submissionEntry->submission = $submissionData; // Process Errors if ($errorMessage) { craft()->urlManager->setRouteVariables(array('errors' => $errorMessage)); } // Process Submission Entry if (!$errorMessage && $spamMethodOne && $spamMethodTwo && $validateRequired) { $submissionResponseId = craft()->formBuilder2_entry->processSubmissionEntry($submissionEntry); // Notify Admin of Submission if ($notificationSettings['notifySubmission'] == '1') { $this->notifyAdminOfSubmission($submissionResponseId, $form); } // Messages if ($formSettings['ajaxSubmit'] == '1') { $this->returnJson(['success' => true, 'message' => $messageSettings['successMessage'], 'form' => $form]); } else { craft()->userSession->setFlash('success', $messageSettings['successMessage']); if ($formSettings['formRedirect']['customRedirect'] != '') { $this->redirect($redirectUrl); } else { $this->redirectToPostedUrl(); } } } else { if ($formSettings['ajaxSubmit'] == '1') { $this->returnJson(['error' => true, 'message' => $messageSettings['errorMessage'], 'form' => $form]); } else { craft()->userSession->setFlash('error', $messageSettings['errorMessage']); } } }
/** * Sends a resource back to the browser. * * @param string $path * * @throws HttpException * @return null */ public function sendResource($path) { if (PathHelper::ensurePathIsContained($path) === false) { throw new HttpException(404); } $cachedPath = $this->getCachedResourcePath($path); if ($cachedPath) { if ($cachedPath == ':(') { // 404 $realPath = false; } else { // We've got it already $realPath = $cachedPath; } } else { // We don't have a cache of the file system path, so let's get it $realPath = $this->getResourcePath($path); // Now cache it $this->cacheResourcePath($path, $realPath); } if ($realPath === false || !IOHelper::fileExists($realPath)) { throw new HttpException(404); } // If there is a timestamp and HTTP_IF_MODIFIED_SINCE exists, check the timestamp against requested file's last // modified date. If the last modified date is less than the timestamp, return a 304 not modified and let the // browser serve it from cache. $timestamp = craft()->request->getParam($this->dateParam, null); if ($timestamp !== null && array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER)) { $requestDate = DateTime::createFromFormat('U', $timestamp); $lastModifiedFileDate = IOHelper::getLastTimeModified($realPath); if ($lastModifiedFileDate && $lastModifiedFileDate <= $requestDate) { // Let the browser serve it from cache. HeaderHelper::setHeader('HTTP/1.1 304 Not Modified'); craft()->end(); } } // Note that $content may be empty -- they could be requesting a blank text file or something. It doens't matter. // No need to throw a 404. $content = IOHelper::getFileContents($realPath); // Normalize URLs in CSS files $mimeType = IOHelper::getMimeTypeByExtension($realPath); if (mb_strpos($mimeType, 'css') !== false) { $content = preg_replace_callback('/(url\\(([\'"]?))(.+?)(\\2\\))/', array(&$this, '_normalizeCssUrl'), $content); } if (!craft()->config->get('useXSendFile')) { $options['forceDownload'] = false; if (craft()->request->getQuery($this->dateParam)) { $options['cache'] = true; } craft()->request->sendFile($realPath, $content, $options); } else { craft()->request->xSendFile($realPath); } // You shall not pass. craft()->end(); }
/** * Sends a file to the user. * * We're overriding this from \CHttpRequest so we can have more control over the headers. * * @param string $path * @param string $content * @param array|null $options * @param bool|null $terminate */ public function sendFile($path, $content, $options = array(), $terminate = true) { $fileName = IOHelper::getFileName($path, true); // Clear the output buffer to prevent corrupt downloads. // Need to check the OB status first, or else some PHP versions will throw an E_NOTICE since we have a custom error handler // (http://pear.php.net/bugs/bug.php?id=9670) if (ob_get_length() !== false) { ob_clean(); } // Default to disposition to 'download' if (!isset($options['forceDownload']) || $options['forceDownload']) { header('Content-Disposition: attachment; filename="' . $fileName . '"'); } if (empty($options['mimeType'])) { if (($options['mimeType'] = \CFileHelper::getMimeTypeByExtension($fileName)) === null) { $options['mimeType'] = 'text/plain'; } } header('Content-type: ' . $options['mimeType']); if (!empty($options['cache'])) { $cacheTime = 31536000; // 1 year header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $cacheTime) . ' GMT'); header('Pragma: cache'); header('Cache-Control: max-age=' . $cacheTime); $modifiedTime = IOHelper::getLastTimeModified($path); header('Last-Modified: ' . gmdate("D, d M Y H:i:s", $modifiedTime->getTimestamp()) . ' GMT'); } else { header('Pragma: public'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); } if (!ob_get_length()) { header('Content-Length: ' . (function_exists('mb_strlen') ? mb_strlen($content, '8bit') : strlen($content))); } if ($options['mimeType'] == 'application/x-javascript' || $options['mimeType'] == 'text/css') { header('Vary: Accept-Encoding'); } if ($terminate) { // clean up the application first because the file downloading could take long time // which may cause timeout of some resources (such as DB connection) ob_start(); Craft::app()->end(0, false); ob_end_clean(); echo $content; exit(0); } else { echo $content; } }
/** * Insert a file into a folder by it's local path. * * @param string $localFilePath The local file path of the file to insert. * @param AssetFolderModel $folder The assetFolderModel where the file should be uploaded to. * @param string $fileName The name of the file to insert. * @param bool $preventConflicts If set to true, will ensure that a conflict is not encountered by * checking the file name prior insertion. * * @return AssetOperationResponseModel */ public function insertFileByPath($localFilePath, AssetFolderModel $folder, $fileName, $preventConflicts = false) { // We hate Javascript and PHP in our image files. if (IOHelper::getFileKind(IOHelper::getExtension($localFilePath)) == 'image' && ImageHelper::isImageManipulatable(IOHelper::getExtension($localFilePath))) { craft()->images->cleanImage($localFilePath); } if ($preventConflicts) { $newFileName = $this->getNameReplacement($folder, $fileName); $response = $this->insertFileInFolder($folder, $localFilePath, $newFileName); } else { $response = $this->insertFileInFolder($folder, $localFilePath, $fileName); // Naming conflict. create a new file and ask the user what to do with it if ($response->isConflict()) { $newFileName = $this->getNameReplacement($folder, $fileName); $conflictResponse = $response; $response = $this->insertFileInFolder($folder, $localFilePath, $newFileName); } } if ($response->isSuccess()) { $filename = IOHelper::getFileName($response->getDataItem('filePath')); $fileModel = new AssetFileModel(); $fileModel->sourceId = $this->model->id; $fileModel->folderId = $folder->id; $fileModel->filename = IOHelper::getFileName($filename); $fileModel->kind = IOHelper::getFileKind(IOHelper::getExtension($filename)); $fileModel->size = filesize($localFilePath); $fileModel->dateModified = IOHelper::getLastTimeModified($localFilePath); if ($fileModel->kind == 'image') { list($width, $height) = getimagesize($localFilePath); $fileModel->width = $width; $fileModel->height = $height; } craft()->assets->storeFile($fileModel); if (!$this->isSourceLocal() && $fileModel->kind == 'image') { craft()->assetTransforms->storeLocalSource($localFilePath, craft()->path->getAssetsImageSourcePath() . $fileModel->id . '.' . IOHelper::getExtension($fileModel->filename)); } // Check if we stored a conflict response originally - send that back then. if (isset($conflictResponse)) { $response = $conflictResponse; } $response->setDataItem('fileId', $fileModel->id); } return $response; }
/** * Get the timestamp of when a file transform was last modified. * * @param AssetFileModel $fileModel * @param string $transformLocation * @return mixed */ public function getTimeTransformModified(AssetFileModel $fileModel, $transformLocation) { $path = $this->_getImageServerPath($fileModel, $transformLocation); if (!IOHelper::fileExists($path)) { return false; } return IOHelper::getLastTimeModified($path); }
/** * Returns the last $number of modified files from a given folder ordered by * the last modified date descending. * * @param string $folder The folder to get the files from. * @param int $number The number of files to return. If null is * given, all files will be returned. * @param bool $suppressErrors Whether to suppress any PHP Notices/Warnings/Errors (usually permissions related). * * @return array */ public static function getLastModifiedFiles($folder, $number = null, $suppressErrors = false) { $fileResults = array(); $files = static::getFiles($folder, $suppressErrors); foreach ($files as $file) { $lastModifiedTime = IOHelper::getLastTimeModified($file, $suppressErrors); $fileResults[$lastModifiedTime->getTimestamp()] = $file; } krsort($fileResults); if ($number !== null) { $fileResults = array_slice($fileResults, 0, $number, true); } return $fileResults; }
/** * Returns a resource URL. * * @param string $path * @param array|string|null $params * @param string|null $protocol The protocol to use (e.g. http, https). If empty, the protocol used for the * current request will be used. * * @return string */ public static function getResourceUrl($path = '', $params = null, $protocol = '') { $path = trim($path, '/'); if ($path) { // If we've served this resource before, we should have a cached copy of the server path already. Use that // to get its timestamp, and add timestamp to the resource URL so ResourcesService sends it with // a Pragma: Cache header. $realPath = craft()->resources->getCachedResourcePath($path); if ($realPath) { if (!is_array($params)) { $params = array($params); } $dateParam = craft()->resources->dateParam; $timeModified = IOHelper::getLastTimeModified($realPath); $params[$dateParam] = $timeModified->getTimestamp(); } } return static::getUrl(craft()->config->getResourceTrigger() . '/' . $path, $params, $protocol); }