/** * Create a new translation from an existing item, switch to this language and reload the tree. */ function createtranslation($data, $form) { $request = $this->owner->getRequest(); // Protect against CSRF on destructive action if (!SecurityToken::inst()->checkRequest($request)) { return $this->owner->httpError(400); } $langCode = Convert::raw2sql($request->postVar('NewTransLang')); $record = $this->owner->getRecord($request->postVar('ID')); if (!$record) { return $this->owner->httpError(404); } $this->owner->Locale = $langCode; Translatable::set_current_locale($langCode); // Create a new record in the database - this is different // to the usual "create page" pattern of storing the record // in-memory until a "save" is performed by the user, mainly // to simplify things a bit. // @todo Allow in-memory creation of translations that don't // persist in the database before the user requests it $translatedRecord = $record->createTranslation($langCode); $url = Controller::join_links($this->owner->Link('show'), $translatedRecord->ID); // set the X-Pjax header to Content, so that the whole admin panel will be refreshed $this->owner->getResponse()->addHeader('X-Pjax', 'Content'); return $this->owner->redirect($url); }
public function sort($request) { if (!SecurityToken::inst()->checkRequest($request)) { $this->httpError(404); } $class = $request->postVar('class'); $ids = $request->postVar('id'); if ($class == 'WorkflowAction') { $objects = $this->Definition()->Actions(); } elseif ($class == 'WorkflowTransition') { $parent = $request->postVar('parent'); $action = $this->Definition()->Actions()->byID($parent); if (!$action) { $this->httpError(400, _t('AdvancedWorkflowAdmin.INVALIDPARENTID', 'An invalid parent ID was specified.')); } $objects = $action->Transitions(); } else { $this->httpError(400, _t('AdvancedWorkflowAdmin.INVALIDCLASSTOORDER', 'An invalid class to order was specified.')); } if (array_diff($ids, $objects->column('ID'))) { $this->httpError(400, _t('AdvancedWorkflowAdmin.INVALIDIDLIST', 'An invalid list of IDs was provided.')); } singleton('WorkflowService')->reorder($objects, $ids); return new SS_HTTPResponse(null, 200, _t('AdvancedWorkflowAdmin.SORTORDERSAVED', 'The sort order has been saved.')); }
public function update(SS_HTTPRequest $request) { if (!SecurityToken::inst()->checkRequest($request)) { return ''; } $url = $request->postVar('URL'); if (strlen($url)) { $info = Oembed::get_oembed_from_url($url); if ($info && $info->exists()) { $object = EmbeddedObject::create(); $object->Title = $info->title; $object->SourceURL = $url; $object->Width = $info->width; $object->Height = $info->height; $object->ThumbURL = $info->thumbnail_url; $object->Description = $info->description ? $info->description : $info->title; $object->Type = $info->type; $object->EmbedHTML = $info->forTemplate(); $this->object = $object; // needed to make sure the check in FieldHolder works out $object->ID = -1; return $this->FieldHolder(); } else { $this->message = _t('EmbeddedObjectField.ERROR', 'Could not look up provided URL: ' . Convert::raw2xml($url)); return $this->FieldHolder(); } } else { $this->object = null; return $this->FieldHolder(); } }
public function update(SS_HTTPRequest $request) { if (!SecurityToken::inst()->checkRequest($request)) { return ''; } $url = $request->postVar('URL'); if (strlen($url)) { $info = Oembed::get_oembed_from_url($url); $info = Embed\Embed::create($url); if ($info) { $object = EmbeddedObject::create(); $object->setFromEmbed($info); $this->object = $object; // needed to make sure the check in FieldHolder works out $object->ID = -1; return $this->FieldHolder(); } else { $this->message = _t('EmbeddedObjectField.ERROR', 'Could not look up provided URL: ' . Convert::raw2xml($url)); return $this->FieldHolder(); } } else { $this->object = null; return $this->FieldHolder(); } }
public function handleBatchAction($request) { // This method can't be called without ajax. if (!$request->isAjax()) { $this->parentController->redirectBack(); return; } // Protect against CSRF on destructive action if (!SecurityToken::inst()->checkRequest($request)) { return $this->httpError(400); } $actions = $this->batchActions(); $actionClass = $actions[$request->param('BatchAction')]['class']; $actionHandler = new $actionClass(); // Sanitise ID list and query the database for apges $ids = preg_split('/ *, */', trim($request->requestVar('csvIDs'))); foreach ($ids as $k => $v) { if (!is_numeric($v)) { unset($ids[$k]); } } if ($ids) { if (class_exists('Translatable') && SiteTree::has_extension('Translatable')) { Translatable::disable_locale_filter(); } $recordClass = $this->recordClass; $pages = DataObject::get($recordClass)->byIDs($ids); if (class_exists('Translatable') && SiteTree::has_extension('Translatable')) { Translatable::enable_locale_filter(); } $record_class = $this->recordClass; if ($record_class::has_extension('Versioned')) { // If we didn't query all the pages, then find the rest on the live site if (!$pages || $pages->Count() < sizeof($ids)) { $idsFromLive = array(); foreach ($ids as $id) { $idsFromLive[$id] = true; } if ($pages) { foreach ($pages as $page) { unset($idsFromLive[$page->ID]); } } $idsFromLive = array_keys($idsFromLive); $livePages = Versioned::get_by_stage($this->recordClass, 'Live')->byIDs($idsFromLive); if ($pages) { // Can't merge into a DataList, need to condense into an actual list first // (which will retrieve all records as objects, so its an expensive operation) $pages = new ArrayList($pages->toArray()); $pages->merge($livePages); } else { $pages = $livePages; } } } } else { $pages = new ArrayList(); } return $actionHandler->run($pages); }
public function authenticate(SS_HTTPRequest $request) { $token = $this->getToken($request); $user = null; if (!Member::currentUserID() && !$this->allowPublicAccess || $token) { if (!$token) { throw new WebServiceException(403, "Missing token parameter"); } $user = $this->tokenAuthenticator->authenticate($token); if (!$user) { throw new WebServiceException(403, "Invalid user token"); } } else { if ($this->allowSecurityId && Member::currentUserID()) { // we check the SecurityID parameter for the current user $secParam = SecurityToken::inst()->getName(); $securityID = $request->requestVar($secParam); if ($securityID && $securityID != SecurityToken::inst()->getValue()) { throw new WebServiceException(403, "Invalid security ID"); } $user = Member::currentUser(); } } if (!$user && !$this->allowPublicAccess) { throw new WebServiceException(403, "Invalid request"); } // now, if we have an hmacValidator in place, use it if ($this->hmacValidator && $user) { if (!$this->hmacValidator->validateHmac($user, $request)) { throw new WebServiceException(403, "Invalid message"); } } return true; }
/** * Generate a security token. * */ public static function getSecurityToken() { // Ensure the session exists before querying it. if (!Session::request_contains_session_id()) { Session::start(); } return SecurityToken::inst()->getSecurityID(); }
public function saveComplexTableField($data, $form, $params) { $child = new $data['ClassName'](); $child->ParentID = $this->controller->ID; $child->write(); $link = SecurityToken::inst()->addToUrl(Controller::join_links($this->Link(), 'item', $child->ID, 'edit')); Session::set('FormInfo.ComplexTableField_Popup_DetailForm.formError', array('message' => _t('MemberProfiles.SECTIONADDED', 'Profile section added, please edit it below.'), 'type' => 'good')); return Director::redirect($link); }
/** * @param $data * @param $form * @return mixed */ public function doUpload($data, $form) { $material = PresentationSlide::create(); $material->SlideID = $data['Slide']; $material->write(); $this->presentation->Materials()->filter(['ClassName' => 'PresentationSlide'])->removeAll(); $this->presentation->Materials()->add($material); $token = SecurityToken::inst()->getValue(); return $form->controller()->redirect(Controller::join_links($form->controller()->Link(), 'success', "?key={$token}&material={$material->ID}")); }
function handleAction($request) { // This method can't be called without ajax. if (!$this->parentController->isAjax()) { $this->parentController->redirectBack(); return; } // Protect against CSRF on destructive action if (!SecurityToken::inst()->checkRequest($request)) { return $this->httpError(400); } $actions = $this->batchActions(); $actionClass = $actions[$request->param('BatchAction')]['class']; $actionHandler = new $actionClass(); // Sanitise ID list and query the database for apges $ids = split(' *, *', trim($request->requestVar('csvIDs'))); foreach ($ids as $k => $v) { if (!is_numeric($v)) { unset($ids[$k]); } } if ($ids) { if (class_exists('Translatable') && Object::has_extension('SiteTree', 'Translatable')) { Translatable::disable_locale_filter(); } $pages = DataObject::get($this->recordClass, sprintf('"%s"."ID" IN (%s)', ClassInfo::baseDataClass($this->recordClass), implode(", ", $ids))); if (class_exists('Translatable') && Object::has_extension('SiteTree', 'Translatable')) { Translatable::enable_locale_filter(); } if (Object::has_extension($this->recordClass, 'Versioned')) { // If we didn't query all the pages, then find the rest on the live site if (!$pages || $pages->Count() < sizeof($ids)) { foreach ($ids as $id) { $idsFromLive[$id] = true; } if ($pages) { foreach ($pages as $page) { unset($idsFromLive[$page->ID]); } } $idsFromLive = array_keys($idsFromLive); $sql = sprintf('"%s"."ID" IN (%s)', $this->recordClass, implode(", ", $idsFromLive)); $livePages = Versioned::get_by_stage($this->recordClass, 'Live', $sql); if ($pages) { $pages->merge($livePages); } else { $pages = $livePages; } } } } else { $pages = new ArrayList(); } return $actionHandler->run($pages); }
public static function initVisitor() { $secID = SecurityToken::inst()->getSecurityID(); if (!($visitor = self::get()->find('securityID', $secID))) { $referer = isset($_SERVER['HTTP_REFERER']) ? self::getDomain($_SERVER['HTTP_REFERER']) : ""; $searchTerm = ""; // This is a new visitor so lets see if we can find out where they came from $visitor = self::saveVisitor($secID, $_SERVER['REMOTE_ADDR'], $referer, $searchTerm); } return $visitor; }
public static function initVisitor() { $secID = SecurityToken::inst()->getSecurityID(); if (!($visitor = self::get()->find('securityID', $secID))) { $referer = isset($_POST['ref']) ? $_POST['ref'] : ""; $resolution = isset($_POST['res']) ? $_POST['res'] : ""; $platform = isset($_POST['plat']) ? $_POST['plat'] : ""; $searchTerm = ""; // This is a new visitor so lets see if we can find out where they came from $visitor = self::saveVisitor($secID, $_SERVER['REMOTE_ADDR'], $referer, $searchTerm, $resolution, $platform); } return $visitor; }
public function testDeleteActionRemoveRelation() { $this->logInWithPermission('ADMIN'); $config = GridFieldConfig::create()->addComponent(new GridFieldDeleteAction(true)); $gridField = new GridField('testfield', 'testfield', $this->list, $config); $form = new Form(new Controller(), 'mockform', new FieldList(array($this->gridField)), new FieldList()); $stateID = 'testGridStateActionField'; Session::set($stateID, array('grid' => '', 'actionName' => 'deleterecord', 'args' => array('RecordID' => $this->idFromFixture('GridFieldAction_Delete_Team', 'team1')))); $token = SecurityToken::inst(); $request = new SS_HTTPRequest('POST', 'url', array(), array('action_gridFieldAlterAction?StateID=' . $stateID => true, $token->getName() => $token->getValue())); $this->gridField->gridFieldAlterAction(array('StateID' => $stateID), $this->form, $request); $this->assertEquals(2, $this->list->count(), 'User should be able to delete records with ADMIN permission.'); }
public function delete($request) { if (!SecurityToken::inst()->checkRequest($request)) { $this->httpError(400); } if (!$request->isPOST()) { $this->httpError(400); } if (!$this->record->canDelete()) { $this->httpError(403); } $this->record->delete(); return $this->RootField()->forTemplate(); }
function testDeleteWithoutGroupDeletesFromDatabase() { $member1 = $this->objFromFixture('Member', 'member1'); $member1ID = $member1->ID; $group1 = $this->objFromFixture('Group', 'group1'); $response = $this->get('MemberTableFieldTest_Controller'); $token = SecurityToken::inst(); $url = sprintf('MemberTableFieldTest_Controller/FormNoGroup/field/Members/item/%d/delete/?usetestmanifest=1', $member1->ID); $url = $token->addToUrl($url); $response = $this->get($url); $group1->flushCache(); $this->assertNotContains($member1->ID, $group1->Members()->column('ID'), 'Member relation to group is removed'); DataObject::flush_and_destroy_cache(); $this->assertFalse(DataObject::get_by_id('Member', $member1ID), 'Member record is removed from database'); }
function handleAction($request) { // This method can't be called without ajax. if (!Director::is_ajax()) { Director::redirectBack(); return; } // Protect against CSRF on destructive action if (!SecurityToken::inst()->checkRequest($request)) { return $this->httpError(400); } $actions = Object::get_static($this->class, 'batch_actions'); $actionClass = $actions[$request->param('BatchAction')]; $actionHandler = new $actionClass(); // Sanitise ID list and query the database for apges $ids = split(' *, *', trim($request->requestVar('csvIDs'))); foreach ($ids as $k => $v) { if (!is_numeric($v)) { unset($ids[$k]); } } if ($ids) { $pages = DataObject::get('SiteTree', "\"SiteTree\".\"ID\" IN (" . implode(", ", $ids) . ")"); // If we didn't query all the pages, then find the rest on the live site if (!$pages || $pages->Count() < sizeof($ids)) { foreach ($ids as $id) { $idsFromLive[$id] = true; } if ($pages) { foreach ($pages as $page) { unset($idsFromLive[$page->ID]); } } $idsFromLive = array_keys($idsFromLive); // Debug::message("\"SiteTree\".\"ID\" IN (" . implode(", ", $idsFromLive) . ")"); $livePages = Versioned::get_by_stage('SiteTree', 'Live', "\"SiteTree\".\"ID\" IN (" . implode(", ", $idsFromLive) . ")"); if ($pages) { $pages->merge($livePages); } else { $pages = $livePages; } } } else { $pages = new DataObjectSet(); } return $actionHandler->run($pages); }
public function preRequest(\SS_HTTPRequest $request, \Session $session, \DataModel $model) { // Check languages to set $languages = array(); foreach (SpellController::get_locales() as $locale) { $languages[] = i18n::get_locale_name($locale) . '=' . $locale; } // Set settings $editor = Config::inst()->get(__CLASS__, 'editor'); HtmlEditorConfig::get($editor)->enablePlugins('spellchecker'); HtmlEditorConfig::get($editor)->addButtonsToLine(2, 'spellchecker'); $token = SecurityToken::inst(); HtmlEditorConfig::get($editor)->setOption('spellchecker_rpc_url', $token->addToUrl('spellcheck/')); HtmlEditorConfig::get($editor)->setOption('browser_spellcheck', false); HtmlEditorConfig::get($editor)->setOption('spellchecker_languages', '+' . implode(', ', $languages)); return true; }
/** * Commit a page changed via the frontend editing * * @return */ public function frontendCommit() { if (!SecurityToken::inst()->check($this->request->postVar('SecurityID'))) { return singleton('FEUtils')->ajaxResponse('Invalid security token', false); } // Versioned::choose_site_stage(); $urlName = isset($_POST['url']) ? $_POST['url'] : null; if ($urlName) { $obj = $this->Page($urlName); if ($obj->canPublish()) { $obj->write(); $obj->doPublish(); } } // Versioned::choose_site_stage(); $return = new stdClass(); $return->success = 0; $return->message = "Data not found"; $data = isset($_POST['data']) ? $_POST['data'] : null; if ($data) { // deserialise $data = json_decode($data); $topublish = $data->toPublish; foreach ($topublish as $typeInfo => $nothing) { list($type, $id) = explode('-', $typeInfo); if ($id) { // set all the contents on the item $obj = DataObject::get_by_id($type, $id); if ($obj) { if ($obj->FrontendEditAllowed() && $obj->doPublish()) { $return->success = 1; $return->message = _t('FrontendEditing.PUBLISH_SUCCESSFUL', "Successfully published page"); } else { $return->message = _t('FrontendEditing.PUBLISH_NOT_ALLOWED', "You cannot publish that content."); } } else { $return->message = sprintf(_t('FrontendEditing.PAGE_MISSING', 'Page %s could not be found'), $id); } } else { $return->message = sprintf(_t('FrontendEditing.PAGE_MISSING', 'Page %s could not be found'), $id); } } } return Convert::raw2json($return); }
public function index($request) { if (!SecurityToken::inst()->checkRequest($request)) { return $this->httpError(403); } $id = $request->getVar('ID'); if (!$id) { return $this->httpError(400); } $feature = Feature::get()->byId($id); if (!$feature) { return $this->httpError(404); } if (!$feature->canView()) { return $this->httpError(403); } $field = $feature->getValueField()->setName($request->getVar('Name')); return $field->forTemplate(); }
/** * @param $data * @param Form $form * @return bool|SS_HTTPResponse */ public function saveLink($data, Form $form) { $url = $data['Link']; // Attach a protocol if needed if (substr($url, 0, 7) != 'http://' && substr($url, 0, 8) != 'https://') { $url = 'http://' . $url; } if (!filter_var($url, FILTER_VALIDATE_URL)) { $form->sessionMessage('That does not appear to be a valid URL', 'bad'); return $this->Controller()->redirectBack(); } $material = PresentationSlide::create(); $material->Link = $url; $material->write(); $this->presentation->Materials()->filter(['ClassName' => 'PresentationSlide'])->removeAll(); $this->presentation->Materials()->add($material); $token = SecurityToken::inst()->getValue(); return $this->Controller()->redirect(Controller::join_links($this->Controller()->Link(), 'success', "?key={$token}&material={$material->ID}")); }
function testDeleteAllCommentsOnPage() { $second = $this->objFromFixture('Page', 'second'); $this->autoFollowRedirection = false; $this->logInAs('commentadmin'); $response = $this->get($second->RelativeLink()); $token = SecurityToken::inst(); $url = sprintf('PageComment/deleteallcomments?pageid=%d', $second->ID); $url = $token->addToUrl($url); $response = $this->get($url); $response = $this->get($second->RelativeLink()); $secondComments = DataObject::get('PageComment', '"ParentID" = ' . $second->ID); $this->assertNull($secondComments); $first = $this->objFromFixture('Page', 'first'); $firstComments = DataObject::get('PageComment', '"ParentID" = ' . $first->ID); $this->assertNotNull($firstComments); $third = $this->objFromFixture('Page', 'third'); $thirdComments = DataObject::get('PageComment', '"ParentID" = ' . $third->ID); $this->assertEquals($thirdComments->Count(), 3); }
/** * @return Session */ public function getFreshSession() { // set up CSRF token stuff $placeholder = Config::inst()->get('LiveFilesystemPublisher', 'security_token_placeholder'); if ($placeholder) { $sessionKey = SecurityToken::inst()->getName(); // This duplicates the SessionToken functionality exactly // But only requires the one class from Silverstripe LivePubHelper::require_session(); LivePubHelper::add_init_code(' function new_security_token() { require_once("' . BASE_PATH . '/framework/security/RandomGenerator.php"); $generator = new RandomGenerator(); return $_SESSION["' . $sessionKey . '"] = $generator->randomToken("sha1"); } $security_token = isset($_SESSION["' . $sessionKey . '"]) ? $_SESSION["' . $sessionKey . '"] : new_security_token(); ', 'LiveSecurityToken'); return new Session(array($sessionKey => $placeholder)); } else { return new Session(null); } }
public function flagComment(SS_HTTPRequest $request) { // Check Security ID if (!SecurityToken::inst()->check($request->getVar('SecurityID'))) { return $this->owner->httpError(400); } $comment = $this->getComment($request); if (!$comment) { return $this->owner->httpError(404); } if (!$comment->canFlag()) { return Security::permissionFailure($this->owner); } $flagged = $comment->doFlag(); if ($request->isAjax()) { $response = $this->owner->getResponse(); $response->addHeader('Content-Type', 'application/json'); $response->setBody(json_encode(['flagged' => $flagged])); return $response; } return $this->owner->redirect($comment->Link()); }
/** * one stop shop button * @return Object ( * IsConnected, * IsLoggedIn, * Link, * ConnectedName, * ConnectedImageURL * ) */ public static function get_login_button($backURL = "", $member) { //back URL if (!$backURL) { $backURL = $_SERVER['REQUEST_URI']; } $position = strpos($backURL, "?"); if ($position) { $backURL = substr($backURL, 0, $position); } $backURL = str_replace("//", "/", $backURL); $backURL .= "#" . strtolower(self::my_service_name()) . "_tab"; $backURL = "?BackURL=" . urlencode($backURL); //security $token = SecurityToken::inst(); if ($member->exists()) { //AJAX FUNCTIONALITY //Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js'); //Requirements::javascript(THIRDPARTY_DIR . '/jquery-livequery/jquery.livequery.js'); //Requirements::javascript('social_integration/javascript/'.strtolower(self::my_service_name()).".js"); $method = "has" . self::my_service_name(); if ($member->{$method}()) { $removeURL = Controller::join_links(self::my_class_name(), 'remove', $backURL); $removeURL = $token->addToUrl($removeURL); $nameField = self::my_service_name() . "Name"; $pictureField = self::my_service_name() . "Picture"; return new ArrayData(array("IsConnected" => true, "IsLoggedIn" => Member::currentUserID() == $member->ID ? true : false, "Link" => $removeURL, "ConnectedName" => $member->{$nameField}, "ConnectedImageURL" => $member->{$pictureField})); } else { $connectURL = Controller::join_links(self::my_class_name(), self::my_service_name() . 'Connect', $backURL); $connectURL = $token->addToUrl($connectURL); return new ArrayData(array("IsConnected" => false, "IsLoggedIn" => Member::currentUserID() == $member->ID ? true : false, "Link" => $connectURL, "ConnectedName" => "", "ConnectedImageURL" => "")); } } else { $connectURL = Controller::join_links(self::my_class_name(), self::my_service_name() . 'Connect', $backURL); $connectURL = $token->addToUrl($connectURL); return new ArrayData(array("IsConnected" => false, "IsLoggedIn" => false, "Link" => $connectURL, "ConnectedName" => "", "ConnectedImageURL" => "")); } }
/** * Invoke a batch action * * @param SS_HTTPRequest $request * @return SS_HTTPResponse */ public function handleBatchAction($request) { // This method can't be called without ajax. if (!$request->isAjax()) { return $this->parentController->redirectBack(); } // Protect against CSRF on destructive action if (!SecurityToken::inst()->checkRequest($request)) { return $this->httpError(400); } // Find the action handler $action = $request->param('BatchAction'); $actionHandler = $this->actionByName($action); // Sanitise ID list and query the database for apges $csvIDs = $request->requestVar('csvIDs'); $ids = $this->cleanIDs($csvIDs); // Filter ids by those which are applicable to this action // Enforces front end filter in LeftAndMain.BatchActions.js:refreshSelected $ids = $actionHandler->applicablePages($ids); // Query ids and pass to action to process $pages = $this->getPages($ids); return $actionHandler->run($pages); }
/** * Tests security ID check */ public function testSecurityID() { // Mock token $securityToken = SecurityToken::inst(); $generator = new RandomGenerator(); $token = $generator->randomToken('sha1'); $session = array($securityToken->getName() => $token); $tokenError = _t('SpellController.SecurityMissing', 'Your session has expired. Please refresh your browser to continue.'); // Test request sans token $response = $this->get('spellcheck', Injector::inst()->create('Session', $session)); $this->assertEquals(400, $response->getStatusCode()); $jsonBody = json_decode($response->getBody()); $this->assertEquals($tokenError, $jsonBody->error->errstr); // Test request with correct token (will fail with an unrelated error) $response = $this->get('spellcheck/?SecurityID=' . urlencode($token), Injector::inst()->create('Session', $session)); $jsonBody = json_decode($response->getBody()); $this->assertNotEquals($tokenError, $jsonBody->error->errstr); // Test request with check disabled Config::inst()->update('SpellController', 'enable_security_token', false); $response = $this->get('spellcheck', Injector::inst()->create('Session', $session)); $jsonBody = json_decode($response->getBody()); $this->assertNotEquals($tokenError, $jsonBody->error->errstr); }
/** * Create a new translation from an existing item, switch to this language and reload the tree. */ function createtranslation($data, $form) { $request = $this->owner->getRequest(); // Protect against CSRF on destructive action if (!SecurityToken::inst()->checkRequest($request)) { return $this->owner->httpError(400); } $langCode = Convert::raw2sql($request->postVar('NewTransLang')); $record = $this->owner->getRecord($request->postVar('ID')); if (!$record) { return $this->httpError(404); } $this->owner->Locale = $langCode; Translatable::set_current_locale($langCode); // Create a new record in the database - this is different // to the usual "create page" pattern of storing the record // in-memory until a "save" is performed by the user, mainly // to simplify things a bit. // @todo Allow in-memory creation of translations that don't persist in the database before the user requests it $translatedRecord = $record->createTranslation($langCode); $url = sprintf("%s/%d/?locale=%s", singleton('CMSPageEditController')->Link('show'), $translatedRecord->ID, $langCode); return $this->owner->redirect($url); }
public function duplicatewithchildren($request) { // Protect against CSRF on destructive action if (!SecurityToken::inst()->checkRequest($request)) { return $this->httpError(400); } if (($id = $this->urlParams['ID']) && is_numeric($id)) { $page = DataObject::get_by_id("SiteTree", $id); if ($page && (!$page->canEdit() || !$page->canCreate())) { return Security::permissionFailure($this); } if (!$page || !$page->ID) { throw new SS_HTTPResponse_Exception("Bad record ID #{$id}", 404); } $newPage = $page->duplicateWithChildren(); // Reload form, data and actions might have changed $form = $this->getEditForm($newPage->ID); return $form->forTemplate()->RAW(); } else { user_error("CMSMain::duplicate() Bad ID: '{$id}'", E_USER_WARNING); } }
public function testDisableSecurityTokenAcceptsSubmissionWithoutToken() { SecurityToken::enable(); $expectedToken = SecurityToken::inst()->getValue(); $response = $this->get('FormTest_ControllerWithSecurityToken'); // can't use submitForm() as it'll automatically insert SecurityID into the POST data $response = $this->post('FormTest_ControllerWithSecurityToken/Form', array('Email' => '*****@*****.**', 'action_doSubmit' => 1)); $this->assertEquals(400, $response->getStatusCode(), 'Submission fails without security token'); // Generate a new token which doesn't match the current one $generator = new RandomGenerator(); $invalidToken = $generator->randomToken('sha1'); $this->assertNotEquals($invalidToken, $expectedToken); // Test token with request $response = $this->get('FormTest_ControllerWithSecurityToken'); $response = $this->post('FormTest_ControllerWithSecurityToken/Form', array('Email' => '*****@*****.**', 'action_doSubmit' => 1, 'SecurityID' => $invalidToken)); $this->assertEquals(200, $response->getStatusCode(), 'Submission reloads form if security token invalid'); $this->assertTrue(stripos($response->getBody(), 'name="SecurityID" value="' . $expectedToken . '"') !== false, 'Submission reloads with correct security token after failure'); $this->assertTrue(stripos($response->getBody(), 'name="SecurityID" value="' . $invalidToken . '"') === false, 'Submission reloads without incorrect security token after failure'); $matched = $this->cssParser()->getBySelector('#Form_Form_Email'); $attrs = $matched[0]->attributes(); $this->assertEquals('*****@*****.**', (string) $attrs['value'], 'Submitted data is preserved'); $response = $this->get('FormTest_ControllerWithSecurityToken'); $tokenEls = $this->cssParser()->getBySelector('#Form_Form_SecurityID'); $this->assertEquals(1, count($tokenEls), 'Token form field added for controller without disableSecurityToken()'); $token = (string) $tokenEls[0]; $response = $this->submitForm('Form_Form', null, array('Email' => '*****@*****.**', 'SecurityID' => $token)); $this->assertEquals(200, $response->getStatusCode(), 'Submission suceeds with security token'); }
public function index() { $this->setHeaders(); // Check security token if (self::config()->enable_security_token && !SecurityToken::inst()->checkRequest($this->request)) { return $this->error(_t('SpellController.SecurityMissing', 'Your session has expired. Please refresh your browser to continue.'), 400); } // Check permission $permission = self::config()->required_permission; if ($permission && !Permission::check($permission)) { return $this->error(_t('SpellController.SecurityDenied', 'Permission Denied'), 403); } // Check data $data = $this->getRequestData(); if (empty($data)) { return $this->error(_t('SpellController.MissingData', "Could not get raw post data"), 400); } // Check params and request type if (!Director::is_ajax() || empty($data['method']) || empty($data['params']) || count($data['params']) < 2) { return $this->error(_t('SpellController.InvalidRequest', 'Invalid request'), 400); } // Check locale $params = $data['params']; $locale = $params[0]; if (!in_array($locale, self::get_locales())) { return $this->error(_t('SpellController.InvalidLocale', 'Not supported locale'), 400); } // Check provider $provider = $this->getProvider(); if (empty($provider)) { return $this->error(_t('SpellController.MissingProviders', "No spellcheck module installed"), 500); } // Perform action try { $method = $data['method']; $words = $params[1]; switch ($method) { case 'checkWords': return $this->success($provider->checkWords($locale, $words)); case 'getSuggestions': return $this->success($provider->getSuggestions($locale, $words)); default: return $this->error(_t('SpellController.UnsupportedMethod', "Unsupported method '{method}'", array('method' => $method)), 400); } } catch (SpellException $ex) { return $this->error($ex->getMessage(), $ex->getCode()); } }