function processRawFieldData($data, &$status, $simulate = false, $entry_id = NULL) { $status = self::__OK__; $timestamp = NULL; if ($data != '') { $timestamp = strtotime($data); } return array('value' => DateTimeObj::get('c', $timestamp), 'local' => strtotime(DateTimeObj::get('c', $timestamp)), 'gmt' => strtotime(DateTimeObj::getGMT('c', $timestamp))); }
public function write() { $section = $this->section->get('object'); $entry = null; $entry_data = array(); // If it's an existing entry we want to load that entry object foreach ($this->writes as $write) { $field = $write->get('object'); $field_data = $write->get('data'); if ($field == SymQuery::SYSTEM_ID) { $existing = SymQuery::$em->fetch($field_data, $section->get('id')); if (is_array($existing) && !empty($existing)) { $entry = current($existing); break; } } } // If $entry is null, then it's a new entry, so fill it with some default metadata if (is_null($entry)) { $entry = SymQuery::$em->create(); $author = SymQuery::$symphony->Author; // Build default entry data: $entry->set('section_id', $section->get('id')); if (is_object($author)) { $entry->set('author_id', $author->get('id')); } $entry->set('creation_date', DateTimeObj::get('Y-m-d H:i:s')); $entry->set('creation_date_gmt', DateTimeObj::getGMT('Y-m-d H:i:s')); } foreach ($this->writes as $write) { $field = $write->get('object'); $field_data = $write->get('data'); if ($field instanceof Field) { $field_handle = $field->get('element_name'); $entry_data[$field_handle] = $field_data; } } if (__ENTRY_FIELD_ERROR__ == $entry->checkPostData($entry_data, $errors, $entry->get('id') ? true : false)) { $validation_errors = array(); foreach ($errors as $field_id => $message) { if (!in_array($field_id, SymQuery::$field_cache)) { SymQuery::$field_cache[$field_id] = SymQuery::$fm->fetch($field_id, $section->get('id')); } $validation_errors[$field_id] = array('field' => SymQuery::$field_cache[$field_id], 'error' => $message); } $error = new SymWriteException('Unable to validate entry.'); $error->setValidationErrors($validation_errors); throw $error; } if (__ENTRY_OK__ != $entry->setDataFromPost($entry_data, $error, false, $entry->get('id') ? true : false)) { throw new SymQueryException(sprintf('Unable to save entry: %s', $error)); } $entry->commit(); return $entry; }
private function parseDate($row) { $fieldname = $this->getFieldName(); if (!empty($row) && isset($row[$fieldname])) { $value = $row[$fieldname] . ' Etc/UTC'; } else { $value = DateTimeObj::getGMT('Y-m-d H:i:s') . ' Etc/UTC'; } $date = DateTimeObj::parse($value); return $date; }
public function processRawFieldData($data, &$status, $simulate = false, $entry_id = NULL) { $status = self::__OK__; $timestamp = null; if (is_null($data) || $data == '') { if ($this->get('pre_populate') == 'yes') { $timestamp = strtotime(DateTimeObj::get(__SYM_DATETIME_FORMAT__, null)); } } else { $timestamp = strtotime($data); } if (!is_null($timestamp)) { return array('value' => DateTimeObj::get('c', $timestamp), 'local' => strtotime(DateTimeObj::get('c', $timestamp)), 'gmt' => strtotime(DateTimeObj::getGMT('c', $timestamp))); } return array('value' => null, 'local' => null, 'gmt' => null); }
function __construct(&$parent) { $this->_Parent = $parent; $this->_fields = array(); $this->_required = false; $this->_showcolumn = true; $this->_handle = strtolower(get_class($this)) == 'field' ? 'field' : strtolower(substr(get_class($this), 5)); if (class_exists('Administration')) { $this->_engine = Administration::instance(); } elseif (class_exists('Frontend')) { $this->_engine = Frontend::instance(); } else { trigger_error(__('No suitable engine object found'), E_USER_ERROR); } $this->creationDate = DateTimeObj::getGMT('c'); $this->Database = Symphony::Database(); }
function __construct(&$parent) { $this->_Parent = $parent; $this->_fields = array(); $this->_required = false; $this->_showcolumn = true; $this->_handle = strtolower(get_class($this)) == 'field' ? 'field' : strtolower(substr(get_class($this), 5)); ## Since we are not sure where the Admin object is, inspect ## all the parent objects $this->catalogueParentObjects(); if (class_exists('Administration')) { $this->_engine = Administration::instance(); } elseif (class_exists('Frontend')) { $this->_engine = Frontend::instance(); } else { trigger_error(__('No suitable engine object found'), E_USER_ERROR); } $this->creationDate = DateTimeObj::getGMT('c'); //$this->_engine->getDateObj(); $this->Database = $this->_engine->Database; }
public function __actionIndex() { $sections_post = @$_POST['sections']; if (empty($this->_driver)) { $this->_driver = $this->_Parent->ExtensionManager->create('section_schemas'); } if (@isset($_POST['action']['save'])) { $blueprint = new contentBlueprintsDatasources(); $sm = new SectionManager($this->_Parent); $sections = $sm->fetch(); foreach ($sections as $section) { $file = DATASOURCES . '/data.section_schema_' . str_replace('-', '_', $section->_data['handle']) . '.php'; General::deleteFile($file); if (in_array($section->_data['handle'], $sections_post)) { $dsShell = file_get_contents(TEMPLATE . '/datasource.tpl'); $dsShell = str_replace("require_once(TOOLKIT . '/class.datasource.php');", "require_once(TOOLKIT . '/class.datasource.php');\n\trequire_once(TOOLKIT . '/class.sectionmanager.php');\n\trequire_once(TOOLKIT . '/class.fieldmanager.php');\n\trequire_once(TOOLKIT . '/class.entrymanager.php');", $dsShell); $dsShell = str_replace('<!-- CLASS NAME -->', 'section_schema_' . str_replace('-', '_', $section->_data['handle']), $dsShell); $dsShell = str_replace('<!-- FILTERS -->', '', $dsShell); $dsShell = str_replace('<!-- INCLUDED ELEMENTS -->', '', $dsShell); $dsShell = str_replace('<!-- DS DEPENDANCY LIST -->', '""', $dsShell); $params['rootelement'] = 'section-schema'; $blueprint->__injectVarList($dsShell, $params); $about = array('name' => 'Section Schema: ' . $section->_data['name'], 'version' => '1.0', 'release date' => DateTimeObj::getGMT('c'), 'author name' => $this->_Parent->Author->getFullName(), 'author website' => URL, 'author email' => $this->_Parent->Author->get('email')); $blueprint->__injectAboutInformation($dsShell, $about); $dsShell = str_replace('<!-- SOURCE -->', $section->_data['id'], $dsShell); $dsShell = str_replace('return true;', 'return false;', $dsShell); $dsShell = str_replace('<!-- GRAB -->', "\$extension = \$this->_Parent->ExtensionManager->create('section_schemas');" . self::CRLF . "\t\t\t\t\$extension->getSectionSchema(\$result, \$this->getSource());", $dsShell); $dsShell = str_replace('<!-- EXTRAS -->', '', $dsShell); if (!is_writable(dirname($file)) || !($write = General::writeFile($file, $dsShell, $this->_Parent->Configuration->get('write_mode', 'file')))) { $this->pageAlert(__('Failed to write data sources to <code>%s</code>. Please check permissions.', array(DATASOURCES)), Alert::ERROR); } else { $this->pageAlert('Section Schema data sources saved.', Alert::SUCCESS); } } } } }
/** * Symphony allows Authors to login via the use of tokens instead of * a username and password. A token is derived from concatenating the * Author's username and password and applying the sha1 hash to * it, from this, a portion of the hash is used as the token. This is a useful * feature often used when setting up other Authors accounts or if an * Author forgets their password. * * @param string $token * The Author token, which is a portion of the hashed string concatenation * of the Author's username and password * @return boolean * True if the Author is logged in, false otherwise */ public function loginFromToken($token) { $token = self::Database()->cleanValue($token); if (strlen(trim($token)) == 0) { return false; } if (strlen($token) == 6) { $row = self::Database()->fetchRow(0, sprintf("\n\t\t\t\t\t\tSELECT `a`.`id`, `a`.`username`, `a`.`password`\n\t\t\t\t\t\tFROM `tbl_authors` AS `a`, `tbl_forgotpass` AS `f`\n\t\t\t\t\t\tWHERE `a`.`id` = `f`.`author_id`\n\t\t\t\t\t\tAND `f`.`expiry` > '%s'\n\t\t\t\t\t\tAND `f`.`token` = '%s'\n\t\t\t\t\t\tLIMIT 1\n\t\t\t\t\t", DateTimeObj::getGMT('c'), $token)); self::Database()->delete('tbl_forgotpass', " `token` = '{$token}' "); } else { $row = self::Database()->fetchRow(0, sprintf("SELECT `id`, `username`, `password`\n\t\t\t\t\tFROM `tbl_authors`\n\t\t\t\t\tWHERE SUBSTR(%s(CONCAT(`username`, `password`)), 1, 8) = '%s'\n\t\t\t\t\tAND `auth_token_active` = 'yes'\n\t\t\t\t\tLIMIT 1", 'SHA1', $token)); } if ($row) { $this->Author = AuthorManager::fetchByID($row['id']); $this->Cookie->set('username', $row['username']); $this->Cookie->set('pass', $row['password']); self::Database()->update(array('last_seen' => DateTimeObj::getGMT('Y-m-d H:i:s')), 'tbl_authors', " `id` = '{$id}'"); return true; } return false; }
public function __actionNew() { if (array_key_exists('save', $_POST['action']) || array_key_exists("done", $_POST['action'])) { $section_id = SectionManager::fetchIDFromHandle($this->_context['section_handle']); if (!($section = SectionManager::fetch($section_id))) { Administration::instance()->customError(__('Unknown Section'), __('The Section you are looking for, %s, could not be found.', array('<code>' . $this->_context['section_handle'] . '</code>'))); } $entry =& EntryManager::create(); $entry->set('section_id', $section_id); $entry->set('author_id', Administration::instance()->Author->get('id')); $entry->set('creation_date', DateTimeObj::get('Y-m-d H:i:s')); $entry->set('creation_date_gmt', DateTimeObj::getGMT('Y-m-d H:i:s')); $fields = $_POST['fields']; // Combine FILES and POST arrays, indexed by their custom field handles if (isset($_FILES['fields'])) { $filedata = General::processFilePostData($_FILES['fields']); foreach ($filedata as $handle => $data) { if (!isset($fields[$handle])) { $fields[$handle] = $data; } elseif (isset($data['error']) && $data['error'] == 4) { $fields['handle'] = NULL; } else { foreach ($data as $ii => $d) { if (isset($d['error']) && $d['error'] == 4) { $fields[$handle][$ii] = NULL; } elseif (is_array($d) && !empty($d)) { foreach ($d as $key => $val) { $fields[$handle][$ii][$key] = $val; } } } } } } // Initial checks to see if the Entry is ok if (__ENTRY_FIELD_ERROR__ == $entry->checkPostData($fields, $this->_errors)) { $this->pageAlert(__('Some errors were encountered while attempting to save.'), Alert::ERROR); } else { if (__ENTRY_OK__ != $entry->setDataFromPost($fields, $errors)) { foreach ($errors as $field_id => $message) { $this->pageAlert($message, Alert::ERROR); } } else { /** * Just prior to creation of an Entry * * @delegate EntryPreCreate * @param string $context * '/publish/new/' * @param Section $section * @param Entry $entry * @param array $fields */ Symphony::ExtensionManager()->notifyMembers('EntryPreCreate', '/publish/new/', array('section' => $section, 'entry' => &$entry, 'fields' => &$fields)); // Check to see if the dancing was premature if (!$entry->commit()) { define_safe('__SYM_DB_INSERT_FAILED__', true); $this->pageAlert(NULL, Alert::ERROR); } else { /** * Creation of an Entry. New Entry object is provided. * * @delegate EntryPostCreate * @param string $context * '/publish/new/' * @param Section $section * @param Entry $entry * @param array $fields */ Symphony::ExtensionManager()->notifyMembers('EntryPostCreate', '/publish/new/', array('section' => $section, 'entry' => $entry, 'fields' => $fields)); $prepopulate_querystring = ''; if (isset($_POST['prepopulate'])) { foreach ($_POST['prepopulate'] as $field_id => $value) { $prepopulate_querystring .= sprintf("prepopulate[%s]=%s&", $field_id, rawurldecode($value)); } $prepopulate_querystring = trim($prepopulate_querystring, '&'); } redirect(sprintf('%s/publish/%s/edit/%d/created/%s', SYMPHONY_URL, $this->_context['section_handle'], $entry->get('id'), !empty($prepopulate_querystring) ? "?" . $prepopulate_querystring : NULL)); } } } } }
public function action() { if (isset($_POST['action'])) { $actionParts = array_keys($_POST['action']); $action = end($actionParts); // Login Attempted if ($action == 'login') { if (empty($_POST['username']) || empty($_POST['password']) || !Administration::instance()->login($_POST['username'], $_POST['password'])) { /** * A failed login attempt into the Symphony backend * * @delegate AuthorLoginFailure * @since Symphony 2.2 * @param string $context * '/login/' * @param string $username * The username of the Author who attempted to login. */ Symphony::ExtensionManager()->notifyMembers('AuthorLoginFailure', '/login/', array('username' => Symphony::Database()->cleanValue($_POST['username']))); $this->failedLoginAttempt = true; } else { /** * A successful login attempt into the Symphony backend * * @delegate AuthorLoginSuccess * @since Symphony 2.2 * @param string $context * '/login/' * @param string $username * The username of the Author who logged in. */ Symphony::ExtensionManager()->notifyMembers('AuthorLoginSuccess', '/login/', array('username' => Symphony::Database()->cleanValue($_POST['username']))); isset($_POST['redirect']) ? redirect($_POST['redirect']) : redirect(SYMPHONY_URL . '/'); } // Reset of password requested } elseif ($action == 'reset') { $author = Symphony::Database()->fetchRow(0, sprintf("\n SELECT `id`, `email`, `first_name`\n FROM `tbl_authors`\n WHERE `email` = '%1\$s' OR `username` = '%1\$s'\n ", Symphony::Database()->cleanValue($_POST['email']))); if (!empty($author)) { Symphony::Database()->delete('tbl_forgotpass', sprintf("\n `expiry` < %d", DateTimeObj::getGMT('c'))); if (!($token = Symphony::Database()->fetchVar('token', 0, "SELECT `token` FROM `tbl_forgotpass` WHERE `expiry` > '" . DateTimeObj::getGMT('c') . "' AND `author_id` = " . $author['id']))) { // More secure password token generation if (function_exists('openssl_random_pseudo_bytes')) { $seed = openssl_random_pseudo_bytes(16); } else { $seed = mt_rand(); } $token = substr(SHA1::hash($seed), 0, 16); Symphony::Database()->insert(array('author_id' => $author['id'], 'token' => $token, 'expiry' => DateTimeObj::getGMT('c', time() + 120 * 60)), 'tbl_forgotpass'); } try { $email = Email::create(); $email->recipients = $author['email']; $email->subject = __('New Symphony Account Password'); $email->text_plain = __('Hi %s,', array($author['first_name'])) . PHP_EOL . __('A new password has been requested for your account. Login using the following link, and change your password via the Authors area:') . PHP_EOL . PHP_EOL . ' ' . SYMPHONY_URL . "/login/{$token}/" . PHP_EOL . PHP_EOL . __('It will expire in 2 hours. If you did not ask for a new password, please disregard this email.') . PHP_EOL . PHP_EOL . __('Best Regards,') . PHP_EOL . __('The Symphony Team'); $email->send(); $this->_email_sent = true; $this->_email_sent_to = $author['email']; // Set this so we can display a customised message } catch (Exception $e) { $this->_email_error = General::unwrapCDATA($e->getMessage()); Symphony::Log()->pushExceptionToLog($e, true); } /** * When a password reset has occurred and after the Password * Reset email has been sent. * * @delegate AuthorPostPasswordResetSuccess * @since Symphony 2.2 * @param string $context * '/login/' * @param integer $author_id * The ID of the Author who requested the password reset */ Symphony::ExtensionManager()->notifyMembers('AuthorPostPasswordResetSuccess', '/login/', array('author_id' => $author['id'])); } else { /** * When a password reset has been attempted, but Symphony doesn't * recognise the credentials the user has given. * * @delegate AuthorPostPasswordResetFailure * @since Symphony 2.2 * @param string $context * '/login/' * @param string $email * The sanitised Email of the Author who tried to request the password reset */ Symphony::ExtensionManager()->notifyMembers('AuthorPostPasswordResetFailure', '/login/', array('email' => Symphony::Database()->cleanValue($_POST['email']))); $this->_email_sent = false; } } } }
public function __formAction() { $fields = $_POST['fields']; $this->_errors = array(); if (trim($fields['name']) == '') { $this->_errors['name'] = __('This is a required field'); } if (trim($fields['source']) == '') { $this->_errors['source'] = __('This is a required field'); } $filters = is_array($fields['filters']) ? $fields['filters'] : array(); $classname = Lang::createHandle($fields['name'], NULL, '_', false, true, array('@^[^a-z]+@i' => '', '/[^\\w-\\.]/i' => '')); $rootelement = str_replace('_', '-', $classname); $file = EVENTS . '/event.' . $classname . '.php'; $isDuplicate = false; $queueForDeletion = NULL; if ($this->_context[0] == 'new' && is_file($file)) { $isDuplicate = true; } elseif ($this->_context[0] == 'edit') { $existing_handle = $this->_context[1]; if ($classname != $existing_handle && is_file($file)) { $isDuplicate = true; } elseif ($classname != $existing_handle) { $queueForDeletion = EVENTS . '/event.' . $existing_handle . '.php'; } } ##Duplicate if ($isDuplicate) { $this->_errors['name'] = __('An Event with the name <code>%s</code> name already exists', array($classname)); } if (empty($this->_errors)) { $multiple = in_array('expect-multiple', $filters); $eventShell = file_get_contents(TEMPLATE . '/event.tpl'); $about = array('name' => $fields['name'], 'version' => '1.0', 'release date' => DateTimeObj::getGMT('c'), 'author name' => Administration::instance()->Author->getFullName(), 'author website' => URL, 'author email' => Administration::instance()->Author->get('email'), 'trigger condition' => $rootelement); $source = $fields['source']; $filter = NULL; $elements = NULL; $this->__injectAboutInformation($eventShell, $about); $this->__injectFilters($eventShell, $filters); $documentation = NULL; $documentation_parts = array(); $documentation_parts[] = new XMLElement('h3', __('Success and Failure XML Examples')); $documentation_parts[] = new XMLElement('p', __('When saved successfully, the following XML will be returned:')); if ($multiple) { $code = new XMLElement($rootelement); $entry = new XMLElement('entry', NULL, array('index' => '0', 'result' => 'success', 'type' => 'create | edit')); $entry->appendChild(new XMLElement('message', __('Entry [created | edited] successfully.'))); $code->appendChild($entry); } else { $code = new XMLElement($rootelement, NULL, array('result' => 'success', 'type' => 'create | edit')); $code->appendChild(new XMLElement('message', __('Entry [created | edited] successfully.'))); } $documentation_parts[] = self::processDocumentationCode($code); ### $documentation_parts[] = new XMLElement('p', __('When an error occurs during saving, due to either missing or invalid fields, the following XML will be returned') . ($multiple ? __(' (<b>Notice that it is possible to get mixtures of success and failure messages when using the "Allow Multiple" option</b>)') : NULL) . ':'); if ($multiple) { $code = new XMLElement($rootelement); $entry = new XMLElement('entry', NULL, array('index' => '0', 'result' => 'error')); $entry->appendChild(new XMLElement('message', __('Entry encountered errors when saving.'))); $entry->appendChild(new XMLElement('field-name', NULL, array('type' => 'invalid | missing'))); $code->appendChild($entry); $entry = new XMLElement('entry', NULL, array('index' => '1', 'result' => 'success', 'type' => 'create | edit')); $entry->appendChild(new XMLElement('message', __('Entry [created | edited] successfully.'))); $code->appendChild($entry); } else { $code = new XMLElement($rootelement, NULL, array('result' => 'error')); $code->appendChild(new XMLElement('message', __('Entry encountered errors when saving.'))); $code->appendChild(new XMLElement('field-name', NULL, array('type' => 'invalid | missing'))); } $code->setValue('...', false); $documentation_parts[] = self::processDocumentationCode($code); ### if (is_array($filters) && !empty($filters)) { $documentation_parts[] = new XMLElement('p', __('The following is an example of what is returned if any options return an error:')); $code = new XMLElement($rootelement, NULL, array('result' => 'error')); $code->appendChild(new XMLElement('message', __('Entry encountered errors when saving.'))); $code->appendChild(new XMLElement('filter', NULL, array('name' => 'admin-only', 'status' => 'failed'))); $code->appendChild(new XMLElement('filter', __('Recipient not found'), array('name' => 'send-email', 'status' => 'failed'))); $code->setValue('...', false); $documentation_parts[] = self::processDocumentationCode($code); } ### $documentation_parts[] = new XMLElement('h3', __('Example Front-end Form Markup')); $documentation_parts[] = new XMLElement('p', __('This is an example of the form markup you can use on your frontend:')); $container = new XMLElement('form', NULL, array('method' => 'post', 'action' => '', 'enctype' => 'multipart/form-data')); $container->appendChild(Widget::Input('MAX_FILE_SIZE', Symphony::Configuration()->get('max_upload_size', 'admin'), 'hidden')); $sectionManager = new SectionManager($this->_Parent); $section = $sectionManager->fetch($fields['source']); $section_fields = $section->fetchFields(); if (is_array($section_fields) && !empty($section_fields)) { foreach ($section_fields as $f) { if ($f->getExampleFormMarkup() instanceof XMLElement) { $container->appendChild($f->getExampleFormMarkup()); } } } $container->appendChild(Widget::Input('action[' . $rootelement . ']', __('Submit'), 'submit')); $code = $container->generate(true); $documentation_parts[] = self::processDocumentationCode($multiple ? str_replace('fields[', 'fields[0][', $code) : $code); $documentation_parts[] = new XMLElement('p', __('To edit an existing entry, include the entry ID value of the entry in the form. This is best as a hidden field like so:')); $documentation_parts[] = self::processDocumentationCode(Widget::Input('id' . ($multiple ? '[0]' : NULL), 23, 'hidden')); $documentation_parts[] = new XMLElement('p', __('To redirect to a different location upon a successful save, include the redirect location in the form. This is best as a hidden field like so, where the value is the URL to redirect to:')); $documentation_parts[] = self::processDocumentationCode(Widget::Input('redirect', URL . '/success/', 'hidden')); if (in_array('send-email', $filters)) { $documentation_parts[] = new XMLElement('h3', __('Send Notification Email')); $documentation_parts[] = new XMLElement('p', __('Upon the event successfully saving the entry, this option takes input from the form and send an email to the desired recipient. <b>It currently does not work with "Allow Multiple".</b> The following are the recognised fields:')); $documentation_parts[] = self::processDocumentationCode('send-email[sender-email] // ' . __('Optional') . self::CRLF . 'send-email[sender-name] // ' . __('Optional') . self::CRLF . 'send-email[reply-to-email] // ' . __('Optional') . self::CRLF . 'send-email[reply-to-name] // ' . __('Optional') . self::CRLF . 'send-email[subject]' . self::CRLF . 'send-email[body]' . self::CRLF . 'send-email[recipient] // ' . __('list of comma-separated author usernames.')); $documentation_parts[] = new XMLElement('p', __('All of these fields can be set dynamically using the exact field name of another field in the form as shown below in the example form:')); $documentation_parts[] = self::processDocumentationCode('<form action="" method="post"> <fieldset> <label>' . __('Name') . ' <input type="text" name="fields[author]" value="" /></label> <label>' . __('Email') . ' <input type="text" name="fields[email]" value="" /></label> <label>' . __('Message') . ' <textarea name="fields[message]" rows="5" cols="21"></textarea></label> <input name="send-email[sender-email]" value="fields[email]" type="hidden" /> <input name="send-email[sender-name]" value="fields[author]" type="hidden" /> <input name="send-email[reply-to-email]" value="fields[email]" type="hidden" /> <input name="send-email[reply-to-name]" value="fields[author]" type="hidden" /> <input name="send-email[subject]" value="You are being contacted" type="hidden" /> <input name="send-email[body]" value="fields[message]" type="hidden" /> <input name="send-email[recipient]" value="fred" type="hidden" /> <input id="submit" type="submit" name="action[save-contact-form]" value="Send" /> </fieldset> </form>'); } /** * Allows adding documentation for new filters. A reference to the $documentation * array is provided, along with selected filters * @delegate AppendEventFilterDocumentation * @param string $context * '/blueprints/events/(edit|new|info)/' * @param array $selected * An array of all the selected filters for this Event * @param array $documentation * An array of all the documentation XMLElements, passed by reference */ Symphony::ExtensionManager()->notifyMembers('AppendEventFilterDocumentation', '/blueprints/events/' . $this->_context[0] . '/', array('selected' => $filters, 'documentation' => &$documentation_parts)); $documentation = join(self::CRLF, array_map(create_function('$x', 'return rtrim($x->generate(true, 4));'), $documentation_parts)); $documentation = str_replace('\'', '\\\'', $documentation); $eventShell = str_replace('<!-- CLASS NAME -->', $classname, $eventShell); $eventShell = str_replace('<!-- SOURCE -->', $source, $eventShell); $eventShell = str_replace('<!-- DOCUMENTATION -->', General::tabsToSpaces($documentation, 2), $eventShell); $eventShell = str_replace('<!-- ROOT ELEMENT -->', $rootelement, $eventShell); ## Remove left over placeholders $eventShell = preg_replace(array('/<!--[\\w ]++-->/'), '', $eventShell); if ($this->_context[0] == 'new') { /** * Prior to creating an Event, the file path where it will be written to * is provided and well as the contents of that file. * * @delegate EventsPreCreate * @since Symphony 2.2 * @param string $context * '/blueprints/events/' * @param string $file * The path to the Event file * @param string $contents * The contents for this Event as a string passed by reference * @param array $filters * An array of the filters attached to this event */ Symphony::ExtensionManager()->notifyMembers('EventPreCreate', '/blueprints/events/', array('file' => $file, 'contents' => &$eventShell, 'filters' => $filters)); } else { /** * Prior to editing an Event, the file path where it will be written to * is provided and well as the contents of that file. * * @delegate EventPreEdit * @since Symphony 2.2 * @param string $context * '/blueprints/events/' * @param string $file * The path to the Event file * @param string $contents * The contents for this Event as a string passed by reference * @param array $filters * An array of the filters attached to this event */ Symphony::ExtensionManager()->notifyMembers('EventPreEdit', '/blueprints/events/', array('file' => $file, 'contents' => &$eventShell, 'filters' => $filters)); } // Write the file if (!is_writable(dirname($file)) || !($write = General::writeFile($file, $eventShell, Symphony::Configuration()->get('write_mode', 'file')))) { $this->pageAlert(__('Failed to write Event to <code>%s</code>. Please check permissions.', array(EVENTS)), Alert::ERROR); } else { if ($queueForDeletion) { General::deleteFile($queueForDeletion); $sql = "SELECT * FROM `tbl_pages` WHERE `events` REGEXP '[[:<:]]" . $existing_handle . "[[:>:]]' "; $pages = Symphony::Database()->fetch($sql); if (is_array($pages) && !empty($pages)) { foreach ($pages as $page) { $page['events'] = preg_replace('/\\b' . $existing_handle . '\\b/i', $classname, $page['events']); Symphony::Database()->update($page, 'tbl_pages', "`id` = '" . $page['id'] . "'"); } } } if ($this->_context[0] == 'new') { /** * After creating the Event, the path to the Event file is provided * * @delegate EventPostCreate * @since Symphony 2.2 * @param string $context * '/blueprints/events/' * @param string $file * The path to the Event file */ Symphony::ExtensionManager()->notifyMembers('EventPostCreate', '/blueprints/events/', array('file' => $file)); } else { /** * After editing the Event, the path to the Event file is provided * * @delegate EventPostEdit * @since Symphony 2.2 * @param string $context * '/blueprints/events/' * @param string $file * The path to the Event file */ Symphony::ExtensionManager()->notifyMembers('EventPostEdit', '/blueprints/events/', array('file' => $file)); } redirect(SYMPHONY_URL . '/blueprints/events/edit/' . $classname . '/' . ($this->_context[0] == 'new' ? 'created' : 'saved') . '/'); } } }
public function __formAction() { $fields = $_POST['fields']; $this->_errors = array(); $providers = Symphony::ExtensionManager()->getProvidersOf(iProvider::DATASOURCE); $providerClass = null; if (trim($fields['name']) == '') { $this->_errors['name'] = __('This is a required field'); } if ($fields['source'] == 'static_xml') { if (trim($fields['static_xml']) == '') { $this->_errors['static_xml'] = __('This is a required field'); } else { $xml_errors = null; include_once TOOLKIT . '/class.xsltprocess.php'; General::validateXML($fields['static_xml'], $xml_errors, false, new XsltProcess()); if (!empty($xml_errors)) { $this->_errors['static_xml'] = __('XML is invalid.'); } } } elseif (is_numeric($fields['source'])) { if (strlen(trim($fields['max_records'])) == 0 || is_numeric($fields['max_records']) && $fields['max_records'] < 1) { if ($fields['paginate_results'] === 'yes') { $this->_errors['max_records'] = __('A result limit must be set'); } } elseif (!self::__isValidPageString($fields['max_records'])) { $this->_errors['max_records'] = __('Must be a valid number or parameter'); } if (strlen(trim($fields['page_number'])) == 0 || is_numeric($fields['page_number']) && $fields['page_number'] < 1) { if ($fields['paginate_results'] === 'yes') { $this->_errors['page_number'] = __('A page number must be set'); } } elseif (!self::__isValidPageString($fields['page_number'])) { $this->_errors['page_number'] = __('Must be a valid number or parameter'); } // See if a Provided Datasource is saved } elseif (!empty($providers)) { foreach ($providers as $providerClass => $provider) { if ($fields['source'] == call_user_func(array($providerClass, 'getSource'))) { call_user_func_array(array($providerClass, 'validate'), array(&$fields, &$this->_errors)); break; } unset($providerClass); } } $classname = Lang::createHandle($fields['name'], 255, '_', false, true, array('@^[^a-z\\d]+@i' => '', '/[^\\w-\\.]/i' => '')); $rootelement = str_replace('_', '-', $classname); // Check to make sure the classname is not empty after handlisation. if (empty($classname) && !isset($this->_errors['name'])) { $this->_errors['name'] = __('Please ensure name contains at least one Latin-based character.', array($classname)); } $file = DATASOURCES . '/data.' . $classname . '.php'; $isDuplicate = false; $queueForDeletion = null; if ($this->_context[0] == 'new' && is_file($file)) { $isDuplicate = true; } elseif ($this->_context[0] == 'edit') { $existing_handle = $this->_context[1]; if ($classname != $existing_handle && is_file($file)) { $isDuplicate = true; } elseif ($classname != $existing_handle) { $queueForDeletion = DATASOURCES . '/data.' . $existing_handle . '.php'; } } // Duplicate if ($isDuplicate) { $this->_errors['name'] = __('A Data source with the name %s already exists', array('<code>' . $classname . '</code>')); } if (empty($this->_errors)) { $filters = array(); $elements = null; $source = $fields['source']; $params = array('rootelement' => $rootelement); $about = array('name' => $fields['name'], 'version' => 'Symphony ' . Symphony::Configuration()->get('version', 'symphony'), 'release date' => DateTimeObj::getGMT('c'), 'author name' => Symphony::Author()->getFullName(), 'author website' => URL, 'author email' => Symphony::Author()->get('email')); // If there is a provider, get their template if ($providerClass) { $dsShell = file_get_contents(call_user_func(array($providerClass, 'getTemplate'))); } else { $dsShell = file_get_contents($this->getTemplate('blueprints.datasource')); } // Author metadata self::injectAboutInformation($dsShell, $about); // Do dependencies, the template file must have <!-- CLASS NAME --> $dsShell = str_replace('<!-- CLASS NAME -->', $classname, $dsShell); // If there is a provider, let them do the prepartion work if ($providerClass) { $dsShell = call_user_func(array($providerClass, 'prepare'), $fields, $params, $dsShell); } else { switch ($source) { case 'authors': $extends = 'AuthorDatasource'; if (isset($fields['filter']['author'])) { $filters = $fields['filter']['author']; } $elements = $fields['xml_elements']; $params['order'] = $fields['order']; $params['redirectonempty'] = $fields['redirect_on_empty']; $params['redirectonforbidden'] = $fields['redirect_on_forbidden']; $params['redirectonrequired'] = $fields['redirect_on_required']; $params['requiredparam'] = trim($fields['required_url_param']); $params['negateparam'] = trim($fields['negate_url_param']); $params['paramoutput'] = $fields['param']; $params['sort'] = $fields['sort']; break; case 'navigation': $extends = 'NavigationDatasource'; if (isset($fields['filter']['navigation'])) { $filters = $fields['filter']['navigation']; } $params['order'] = $fields['order']; $params['redirectonempty'] = $fields['redirect_on_empty']; $params['redirectonforbidden'] = $fields['redirect_on_forbidden']; $params['redirectonrequired'] = $fields['redirect_on_required']; $params['requiredparam'] = trim($fields['required_url_param']); $params['negateparam'] = trim($fields['negate_url_param']); break; case 'static_xml': $extends = 'StaticXMLDatasource'; $fields['static_xml'] = trim($fields['static_xml']); if (preg_match('/^<\\?xml/i', $fields['static_xml']) == true) { // Need to remove any XML declaration $fields['static_xml'] = preg_replace('/^<\\?xml[^>]+>/i', null, $fields['static_xml']); } $params['static'] = sprintf('%s', trim($fields['static_xml'])); break; default: $extends = 'SectionDatasource'; $elements = $fields['xml_elements']; if (is_array($fields['filter']) && !empty($fields['filter'])) { $filters = array(); foreach ($fields['filter'] as $f) { foreach ($f as $key => $val) { $filters[$key] = $val; } } } $params['order'] = $fields['order']; $params['group'] = $fields['group']; $params['paginateresults'] = $fields['paginate_results']; $params['limit'] = $fields['max_records']; $params['startpage'] = $fields['page_number']; $params['redirectonempty'] = $fields['redirect_on_empty']; $params['redirectonforbidden'] = $fields['redirect_on_forbidden']; $params['redirectonrequired'] = $fields['redirect_on_required']; $params['requiredparam'] = trim($fields['required_url_param']); $params['negateparam'] = trim($fields['negate_url_param']); $params['paramoutput'] = $fields['param']; $params['sort'] = $fields['sort']; $params['htmlencode'] = $fields['html_encode']; $params['associatedentrycounts'] = $fields['associated_entry_counts']; break; } $this->__injectVarList($dsShell, $params); $this->__injectIncludedElements($dsShell, $elements); self::injectFilters($dsShell, $filters); if (preg_match_all('@(\\$ds-[0-9a-z_\\.\\-]+)@i', $dsShell, $matches)) { $dependencies = General::array_remove_duplicates($matches[1]); $dsShell = str_replace('<!-- DS DEPENDENCY LIST -->', "'" . implode("', '", $dependencies) . "'", $dsShell); } $dsShell = str_replace('<!-- CLASS EXTENDS -->', $extends, $dsShell); $dsShell = str_replace('<!-- SOURCE -->', $source, $dsShell); } if ($this->_context[0] == 'new') { /** * Prior to creating the Datasource, the file path where it will be written to * is provided and well as the contents of that file. * * @delegate DatasourcePreCreate * @since Symphony 2.2 * @param string $context * '/blueprints/datasources/' * @param string $file * The path to the Datasource file * @param string $contents * The contents for this Datasource as a string passed by reference * @param array $params * An array of all the `$dsParam*` values * @param array $elements * An array of all the elements included in this datasource * @param array $filters * An associative array of all the filters for this datasource with the key * being the `field_id` and the value the filter. * @param array $dependencies * An array of dependencies that this datasource has */ Symphony::ExtensionManager()->notifyMembers('DatasourcePreCreate', '/blueprints/datasources/', array('file' => $file, 'contents' => &$dsShell, 'params' => $params, 'elements' => $elements, 'filters' => $filters, 'dependencies' => $dependencies)); } else { /** * Prior to editing a Datasource, the file path where it will be written to * is provided and well as the contents of that file. * * @delegate DatasourcePreEdit * @since Symphony 2.2 * @param string $context * '/blueprints/datasources/' * @param string $file * The path to the Datasource file * @param string $contents * The contents for this Datasource as a string passed by reference * @param array $dependencies * An array of dependencies that this datasource has * @param array $params * An array of all the `$dsParam*` values * @param array $elements * An array of all the elements included in this datasource * @param array $filters * An associative array of all the filters for this datasource with the key * being the `field_id` and the value the filter. */ Symphony::ExtensionManager()->notifyMembers('DatasourcePreEdit', '/blueprints/datasources/', array('file' => $file, 'contents' => &$dsShell, 'dependencies' => $dependencies, 'params' => $params, 'elements' => $elements, 'filters' => $filters)); } // Remove left over placeholders $dsShell = preg_replace(array('/<!--[\\w ]++-->/', '/(\\t+[\\r\\n]){2,}/', '/(\\r\\n){2,}/'), '$1', $dsShell); // Write the file if (!is_writable(dirname($file)) || !General::writeFile($file, $dsShell, Symphony::Configuration()->get('write_mode', 'file'), 'w', true)) { $this->pageAlert(__('Failed to write Data source to disk.') . ' ' . __('Please check permissions on %s.', array('<code>/workspace/data-sources</code>')), Alert::ERROR); // Write successful } else { if (function_exists('opcache_invalidate')) { opcache_invalidate($file, true); } // Attach this datasources to pages $connections = $fields['connections']; ResourceManager::setPages(ResourceManager::RESOURCE_TYPE_DS, is_null($existing_handle) ? $classname : $existing_handle, $connections); // If the datasource has been updated and the name changed, then adjust all the existing pages that have the old datasource name if ($queueForDeletion) { General::deleteFile($queueForDeletion); // Update pages that use this DS $pages = PageManager::fetch(false, array('data_sources', 'id'), array("\n `data_sources` REGEXP '[[:<:]]" . $existing_handle . "[[:>:]]'\n ")); if (is_array($pages) && !empty($pages)) { foreach ($pages as $page) { $page['data_sources'] = preg_replace('/\\b' . $existing_handle . '\\b/i', $classname, $page['data_sources']); PageManager::edit($page['id'], $page); } } } if ($this->_context[0] == 'new') { /** * After creating the Datasource, the path to the Datasource file is provided * * @delegate DatasourcePostCreate * @since Symphony 2.2 * @param string $context * '/blueprints/datasources/' * @param string $file * The path to the Datasource file */ Symphony::ExtensionManager()->notifyMembers('DatasourcePostCreate', '/blueprints/datasources/', array('file' => $file)); } else { /** * After editing the Datasource, the path to the Datasource file is provided * * @delegate DatasourcePostEdit * @since Symphony 2.2 * @param string $context * '/blueprints/datasources/' * @param string $file * The path to the Datasource file * @param string $previous_file * The path of the previous Datasource file in the case where a Datasource may * have been renamed. To get the handle from this value, see * `DatasourceManager::__getHandleFromFilename` */ Symphony::ExtensionManager()->notifyMembers('DatasourcePostEdit', '/blueprints/datasources/', array('file' => $file, 'previous_file' => $queueForDeletion ? $queueForDeletion : null)); } redirect(SYMPHONY_URL . '/blueprints/datasources/edit/' . $classname . '/' . ($this->_context[0] == 'new' ? 'created' : 'saved') . '/'); } } }
function action() { if (isset($_POST['action'])) { $actionParts = array_keys($_POST['action']); $action = end($actionParts); ##Login Attempted if ($action == 'login') { if (empty($_POST['username']) || empty($_POST['password']) || !$this->_Parent->login($_POST['username'], $_POST['password'])) { ## TODO: Fix Me ### # Delegate: LoginFailure # Description: Failed login attempt. Username is provided. //$ExtensionManager->notifyMembers('LoginFailure', getCurrentPage(), array('username' => $_POST['username'])); //$this->Body->appendChild(new XMLElement('p', 'Login invalid. <a href="'.URL.'/symphony/?forgot">Forgot your password?</a>')); //$this->_alert = 'Login invalid. <a href="'.URL.'/symphony/?forgot">Forgot your password?</a>'; $this->_invalidPassword = true; } else { ## TODO: Fix Me ### # Delegate: LoginSuccess # Description: Successful login attempt. Username is provided. //$ExtensionManager->notifyMembers('LoginSuccess', getCurrentPage(), array('username' => $_POST['username'])); if (isset($_POST['redirect'])) { redirect(URL . str_replace(parse_url(URL, PHP_URL_PATH), '', $_POST['redirect'])); } redirect(URL . '/symphony/'); } ##Reset of password requested } elseif ($action == 'reset') { $author = $this->_Parent->Database->fetchRow(0, "SELECT `id`, `email`, `first_name` FROM `tbl_authors` WHERE `email` = '" . $_POST['email'] . "'"); if (!empty($author)) { $this->_Parent->Database->delete('tbl_forgotpass', " `expiry` < '" . DateTimeObj::getGMT('c') . "' "); if (!($token = $this->_Parent->Database->fetchVar('token', 0, "SELECT `token` FROM `tbl_forgotpass` WHERE `expiry` > '" . DateTimeObj::getGMT('c') . "' AND `author_id` = " . $author['id']))) { $token = substr(md5(time() . rand(0, 200)), 0, 6); $this->_Parent->Database->insert(array('author_id' => $author['id'], 'token' => $token, 'expiry' => DateTimeObj::getGMT('c', time() + 120 * 60)), 'tbl_forgotpass'); } $this->_email_sent = General::sendEmail($author['email'], $this->_Parent->Database->fetchVar('email', 0, "SELECT `email` FROM `tbl_authors` ORDER BY `id` ASC LIMIT 1"), __('Symphony Concierge'), __('New Symphony Account Password'), __('Hi %s,', array($author['first_name'])) . self::CRLF . __('A new password has been requested for your account. Login using the following link, and change your password via the Authors area:') . self::CRLF . self::CRLF . ' ' . URL . "/symphony/login/{$token}/" . self::CRLF . self::CRLF . __('It will expire in 2 hours. If you did not ask for a new password, please disregard this email.') . self::CRLF . self::CRLF . __('Best Regards,') . self::CRLF . __('The Symphony Team')); ## TODO: Fix Me ### # Delegate: PasswordResetSuccess # Description: A successful password reset has taken place. Author ID is provided //$ExtensionManager->notifyMembers('PasswordResetSuccess', getCurrentPage(), array('author_id' => $author['id'])); } else { ## TODO: Fix Me ### # Delegate: PasswordResetFailure # Description: A failed password reset has taken place. Author ID is provided //$ExtensionManager->notifyMembers('PasswordResetFailure', getCurrentPage(), array('author_id' => $author['id'])); $this->_email_sent = false; } ##Change of password requested } elseif ($action == 'change' && $this->_Parent->isLoggedIn()) { if (empty($_POST['password']) || empty($_POST['password-confirmation']) || $_POST['password'] != $_POST['password-confirmation']) { $this->_mismatchedPassword = true; } else { $author_id = $this->_Parent->Author->get('id'); require_once TOOLKIT . '/class.authormanager.php'; $authorManager = new AuthorManager($this->_Parent); $author = $authorManager->fetchByID($author_id); $author->set('password', md5($this->_Parent->Database->cleanValue($_POST['password']))); if (!$author->commit() || !$this->_Parent->login($author->get('username'), $_POST['password'])) { redirect(URL . "symphony/system/authors/edit/{$author_id}/error/"); } ## TODO: Fix me ### # Delegate: PasswordChanged # Description: After editing an author. ID of the author is provided. //$ExtensionManager->notifyMembers('PasswordChanged', getCurrentPage(), array('author_id' => $author_id)); redirect(URL . '/symphony/'); } } } elseif ($_REQUEST['action'] == 'resetpass' && isset($_REQUEST['token'])) { $sql = "SELECT t1.`id`, t1.`email`, t1.`first_name` \n\t\t\t\t\t FROM `tbl_authors` as t1, `tbl_forgotpass` as t2\n\t\t\t\t\t \tWHERE t2.`token` = '" . $_REQUEST['token'] . "' AND t1.`id` = t2.`author_id`\n\t\t\t\t\t \tLIMIT 1"; $author = $this->_Parent->Database->fetchRow(0, $sql); if (!empty($author)) { $newpass = General::generatePassword(); General::sendEmail($author['email'], '*****@*****.**', 'Symphony Concierge', 'RE: New Symphony Account Password', 'Hi ' . $author['first_name'] . ',' . self::CRLF . "As requested, here is your new Symphony Author Password for '" . URL . "'" . self::CRLF . "\t{$newpass}" . self::CRLF . self::CRLF . 'Best Regards,' . self::CRLF . 'The Symphony Team'); $this->_Parent->Database->update(array('password' => md5($newpass)), 'tbl_authors', " `id` = '" . $author['id'] . "' LIMIT 1"); $this->_Parent->Database->delete('tbl_forgotpass', " `author_id` = '" . $author['id'] . "'"); ## TODO: Fix Me ### # Delegate: PasswordResetRequest # Description: User has requested a password reset. Author ID is provided. //$ExtensionManager->notifyMembers('PasswordResetRequest', getCurrentPage(), array('author_id' => $author['id'])); $this->_alert = 'Password reset. Check your email'; } } }
public function checkPostFieldData($data, &$error = null, $entry_id = null) { if (isset($data['entry']) and is_array($data['entry'])) { $entryManager = new EntryManager(Symphony::Engine()); $fieldManager = new FieldManager(Symphony::Engine()); $field = $fieldManager->fetch($this->get('linked_field_id')); $field_id = $this->get('id'); $status = self::__OK__; $handled_entries = array(); self::$errors[$field_id] = array(); self::$entries[$field_id] = array(); // Create: foreach ($data['entry'] as $index => $entry_data) { $existing_id = null; // Find existing entry: if ((int) $data['entry_id'][$index] > 0) { $entries = $entryManager->fetch((int) $data['entry_id'][$index], $this->get('linked_section_id')); if (isset($entries[0])) { $entry = $entries[0]; $existing_id = $entry->get('id'); } } // Skip duplicate entries: if ($existing_id != null && in_array($existing_id, $handled_entries)) { continue; } // Create a new entry: if ($existing_id == null) { $entry = $entryManager->create(); $entry->set('section_id', $this->get('linked_section_id')); $entry->set('author_id', isset(Symphony::Engine()->Author) ? Symphony::Engine()->Author->get('id') : 1); $entry->set('creation_date', DateTimeObj::get('Y-m-d H:i:s')); $entry->set('creation_date_gmt', DateTimeObj::getGMT('Y-m-d H:i:s')); $entry->assignEntryId(); } // Append correct linked data: $existing_data = $entry->getData($this->get('linked_field_id')); $existing_entries = array(); if (isset($existing_data['linked_entry_id'])) { if (!is_array($existing_data['linked_entry_id'])) { $existing_entries[] = $existing_data['linked_entry_id']; } else { foreach ($existing_data['linked_entry_id'] as $linked_entry_id) { $existing_entries[] = $linked_entry_id; } } } if (!in_array($entry_id, $existing_entries)) { $existing_entries[] = $entry_id; } $entry_data[$field->get('element_name')] = $existing_entries; // Validate: if (__ENTRY_FIELD_ERROR__ == $entry->checkPostData($entry_data, $errors)) { self::$errors[$field_id][$index] = $errors; $status = self::__INVALID_FIELDS__; } if (__ENTRY_OK__ != $entry->setDataFromPost($entry_data, $error)) { $status = self::__INVALID_FIELDS__; } // Cleanup dud entry: if ($existing_id == null and $status != self::__OK__) { $existing_id = $entry->get('id'); $entry->set('id', 0); Symphony::Database()->delete('tbl_entries', " `id` = '{$existing_id}' "); } self::$entries[$field_id][$index] = $entry; $handled_entries[] = $entry->get('id'); } return $status; } return parent::checkPostFieldData($data, $error, $entry_id); }
public function processRawFieldData($data, &$status, &$message = null, $simulate = false, $entry_id = null) { $status = self::__OK__; $timestamp = null; if (is_null($data) || $data == '') { $timestamp = strtotime(Lang::standardizeDate(DateTimeObj::get(__SYM_DATETIME_FORMAT__, null))); } else { $timestamp = strtotime(Lang::standardizeDate($data)); } if (!is_null($timestamp)) { return array('value' => DateTimeObj::get('c', $timestamp), 'date' => DateTimeObj::getGMT('Y-m-d H:i:s', $timestamp)); } return array('value' => null, 'date' => null); }
function __actionDo() { if (!isset($_POST['fields']['source']) or $_POST['fields']['source'] <= 0) { $this->_errors[] = 'You didn\'t choose a source, perhaps you don\'t have any sections with an upload field in them?'; $this->_valid = false; return; } if (!isset($_POST['fields']['sourcedir']) or !preg_match('/^\\/workspace\\/uploads\\/mui/i', $_POST['fields']['sourcedir'])) { $this->_errors[] = 'Fail!'; $this->_valid = false; return; } $this->_section_id = $_POST['fields']['source']; // section id $entryManager = new EntryManager($this->_Parent); $sectionManager = new SectionManager($this->_Parent); $section = $sectionManager->fetch($this->_section_id); // get all the fields for the types we support, and get ready to put the filename in them foreach ($this->_driver->getTypes() as $type) { $f = $section->fetchFields($type); if (count($f) > 0) { foreach ($f as $field) { $field_names[] = $field; } } //array($field->get('element_name'), $field->get('destination')); } $files = General::listStructure(DOCROOT . $_POST['fields']['sourcedir']); if (count($files['filelist']) == 0) { $this->_errors[] = "There are no files in this directory: {$_POST['fields']['sourcedir']}."; $this->_valid = false; return; } // a list of all the entries so we can rollback $entries = array(); foreach ($files['filelist'] as $k => $f) { $continue = false; $this->_files[] = $f; $entry =& $entryManager->create(); $entry->set('section_id', $this->_section_id); $entry->set('author_id', $this->_Parent->Author->get('id')); $entry->set('creation_date', DateTimeObj::get('Y-m-d H:i:s')); $entry->set('creation_date_gmt', DateTimeObj::getGMT('Y-m-d H:i:s')); $chkfields = $fields = $_POST['fields'][$this->_section_id]; // loop over all the supported fields foreach ($field_names as $field) { $dest = $field->get('destination'); $name = $field->get('element_name'); $tmp_name = DOCROOT . $_POST['fields']['sourcedir'] . '/' . $f; $new_name = DOCROOT . $dest . '/' . $f; /* if you don't want to rollback implement this */ // if($field->get('validator') != NULL){ // $rule = $field->get('validator'); // // // skip this file since it doesn't validate // if(!General::validateString($tmp_name, $rule)) { // ; // // $continue = true; // } // } $type = trim(shell_exec('file -b --mime ' . escapeshellarg($tmp_name))); $size = filesize($tmp_name); // setup fields to check the post $chkfields[$name][name] = $f; $chkfields[$name][type] = $type; $chkfields[$name][tmp_name] = $tmp_name; $chkfields[$name][error] = 0; $chkfields[$name][size] = $size; // an array to copy the files after $copy[] = array($tmp_name, $new_name); // setup upload fields as they should be as if they were processed $fields[$name][file] = preg_replace("/^\\/workspace/", '', $dest) . '/' . $f; $fields[$name][size] = $size; $fields[$name][mimetype] = $type; $fields[$name][meta] = serialize($this->getMetaInfo(DOCROOT . $fields[$name][file], $type)); } // skip the file if it doesn't validate // if ($continue == true) continue; if (__ENTRY_FIELD_ERROR__ == $entry->checkPostData($chkfields, $this->_errors)) { $this->_ignored_files[] = $f; break; } // now we can copy the files to their new location since everything's validated foreach ($copy as $c) { if (@copy($c[0], $c[1])) { @chmod($c[1], intval(0755, 8)); } else { $this->_errors[] = "Couldn't copy the files to the {$dest} directory. "; return; } } // setup the data, process it if (__ENTRY_OK__ != $this->setDataFromPost($entry, $fields, $this->_errors, false, false, $entries)) { $this->_ignored_files[] = $f; break; } // commit the entry if we made it if (!$entry->commit()) { define_safe('__SYM_DB_INSERT_FAILED__', true); } else { $this->_valid = true; } } // rollback, delete all entries by id if ($this->_valid == false && count($entries) > 0) { $entryManager->delete($entries); return; } // if we made it here, and they want us to delete the files, it shall beDOCROOT . $_POST['fields']['sourcedir'] if (isset($_POST['fields']['remove']) && $_POST['fields']['remove'] == 'on' && $this->_valid == true) { foreach ($files['filelist'] as $k => $f) { unlink(DOCROOT . $_POST['fields']['sourcedir'] . '/' . $f); } // already sanitized the sourcedir so no one can accidentally delete stuff // from anywhere but the uploads directory, make sure not to delete mui dir if ($_POST['fields']['sourcedir'] != '/workspace' . $this->_driver->getMUI()) { rmdir(DOCROOT . $_POST['fields']['sourcedir']); } } $this->_entries_count = count($files['filelist']) - count($this->_ignored_files); }
public function save(MessageStack $errors) { $editing = isset($this->parameters()->{'root-element'}) ? $this->parameters()->{'root-element'} : false; // About info: if (!isset($this->about()->name) || empty($this->about()->name)) { $errors->append('about::name', __('This is a required field')); } try { $existing = self::loadFromHandle($this->handle); } catch (DataSourceException $e) { // Datasource not found, continue! } if ($existing instanceof Datasource && $editing != $this->handle) { throw new DataSourceException(__('A Datasource with the name <code>%s</code> already exists', array($this->about()->name))); } // Save type: if ($errors->length() <= 0) { $user = Administration::instance()->User; if (!file_exists($this->getTemplate())) { $errors->append('write', __("Unable to find Data Source Type template '%s'.", array($this->getTemplate()))); throw new DataSourceException(__("Unable to find Data Source Type template '%s'.", array($this->getTemplate()))); } $this->parameters()->{'root-element'} = $this->handle; $classname = Lang::createHandle(ucwords($this->about()->name), '_', false, true, array('/[^a-zA-Z0-9_\\x7f-\\xff]/' => NULL), true); $pathname = DATASOURCES . "/" . $this->handle . ".php"; $data = array($classname, var_export($this->about()->name, true), var_export($user->getFullName(), true), var_export(URL, true), var_export($user->email, true), var_export('1.0', true), var_export(DateTimeObj::getGMT('c'), true)); foreach ($this->parameters() as $value) { $data[] = trim(General::var_export($value, true, is_array($value) ? 5 : 0)); } if (General::writeFile($pathname, vsprintf(file_get_contents($this->getTemplate()), $data), Symphony::Configuration()->core()->symphony->{'file-write-mode'})) { if ($editing !== false && $editing != $this->handle) { General::deleteFile(DATASOURCES . '/' . $editing . '.php'); } return $pathname; } $errors->append('write', __('Failed to write datasource "%s" to disk.', array($filename))); } throw new DataSourceException('Errors were encountered whilst attempting to save.'); }
/** * Iterates over all the Fields in this Entry calling their * `processRawFieldData()` function to set default values for this Entry. * * @see toolkit.Field#processRawFieldData() */ public function findDefaultData() { $section = SectionManager::fetch($this->get('section_id')); $schema = $section->fetchFields(); foreach ($schema as $field) { if (isset($this->_data[$field->get('field_id')])) { continue; } $result = $field->processRawFieldData(null, $status, $message, false, $this->get('id')); $this->setData($field->get('field_id'), $result); } if (!$this->get('creation_date')) { $this->set('creation_date', DateTimeObj::get('c')); } if (!$this->get('creation_date_gmt')) { $this->set('creation_date_gmt', DateTimeObj::getGMT('c')); } }
public function loginFromToken($token) { $token = self::$Database->cleanValue($token); if (strlen(trim($token)) == 0) { return false; } if (strlen($token) == 6) { $row = self::$Database->fetchRow(0, "SELECT `a`.`id`, `a`.`username`, `a`.`password` \n\t\t\t\t\t\t\t\t\t\t\t\t\t FROM `tbl_authors` AS `a`, `tbl_forgotpass` AS `f`\n\t\t\t\t\t\t\t\t\t\t\t\t\t WHERE `a`.`id` = `f`.`author_id` AND `f`.`expiry` > '" . DateTimeObj::getGMT('c') . "' AND `f`.`token` = '{$token}'\n\t\t\t\t\t\t\t\t\t\t\t\t\t LIMIT 1"); self::$Database->delete('tbl_forgotpass', " `token` = '{$token}' "); } else { $row = self::$Database->fetchRow(0, "SELECT `id`, `username`, `password` \n\t\t\t\t\t\t\t\t\t\t\t\t\t FROM `tbl_authors` \n\t\t\t\t\t\t\t\t\t\t\t\t\t WHERE SUBSTR(MD5(CONCAT(`username`, `password`)), 1, 8) = '{$token}' AND `auth_token_active` = 'yes' \n\t\t\t\t\t\t\t\t\t\t\t\t\t LIMIT 1"); } if ($row) { $this->_user_id = $row['id']; $this->Author = new Author($row['id']); $this->Cookie->set('username', $row['username']); $this->Cookie->set('pass', $row['password']); self::$Database->update(array('last_seen' => DateTimeObj::getGMT('Y-m-d H:i:s')), 'tbl_authors', " `id` = '{$id}'"); $this->reloadLangFromAuthorPreference(); return true; } return false; }
public function checkPostFieldData($data, &$error = null, $entry_id = null) { $field = self::$fieldManager->fetch($this->get('child_field_id')); $status = self::__OK__; $data = $this->getData(); // Create: if (is_array($data)) { foreach ($data['entry'] as $index => $entry_data) { $existing_id = $data['entry_id'][$index]; if (empty($existing_id)) { $entry = self::$entryManager->create(); $entry->set('section_id', $this->get('child_section_id')); $entry->set('author_id', $this->_engine->Author->get('id')); $entry->set('creation_date', DateTimeObj::get('Y-m-d H:i:s')); $entry->set('creation_date_gmt', DateTimeObj::getGMT('Y-m-d H:i:s')); } else { $entry = @current(self::$entryManager->fetch($existing_id, $this->get('child_section_id'))); } // Create link: if ($field) { $entry_data[$field->get('element_name')] = array('parent_entry_id' => $entry_id); } // Validate: if (__ENTRY_FIELD_ERROR__ == $entry->checkPostData($entry_data, $errors)) { if (!empty($errors)) { self::$errors[$this->get('id')][$index] = $errors; } $status = self::__INVALID_FIELDS__; } elseif (__ENTRY_OK__ != $entry->setDataFromPost($entry_data, $error)) { $status = self::__INVALID_FIELDS__; } self::$entries[$this->get('id')][] = $entry; } } return $status; }
function __actionEdit() { if (!($author_id = $this->_context[1])) { redirect(URL . '/symphony/system/authors/'); } $isOwner = $author_id == $this->_Parent->Author->get('id'); if (@array_key_exists('save', $_POST['action']) || @array_key_exists('done', $_POST['action'])) { $fields = $_POST['fields']; $this->_Author =& $this->_AuthorManager->fetchByID($author_id); $authenticated = false; if ($fields['email'] != $this->_Author->get('email')) { $changing_email = true; } if (trim($fields['old-password']) != '' && md5(trim($fields['old-password'])) == $this->_Author->get('password')) { $authenticated = true; } $this->_Author->set('id', $author_id); if (isset($fields['user_type'])) { $this->_Author->set('user_type', $fields['user_type']); } $this->_Author->set('email', $fields['email']); $this->_Author->set('username', $fields['username']); $this->_Author->set('first_name', General::sanitize($fields['first_name'])); $this->_Author->set('last_name', General::sanitize($fields['last_name'])); if (trim($fields['password']) != '') { $this->_Author->set('password', md5($fields['password'])); $changing_password = true; } $this->_Author->set('default_section', intval($fields['default_section'])); $this->_Author->set('auth_token_active', $fields['auth_token_active'] ? $fields['auth_token_active'] : 'no'); if ($this->_Author->validate($this->_errors)) { if (!$authenticated && ($changing_password || $changing_email)) { if ($changing_password) { $this->_errors['old-password'] = __('Wrong password. Enter old password to change it.'); } elseif ($changing_email) { $this->_errors['old-password'] = __('Wrong password. Enter old one to change email address.'); } } elseif (($fields['password'] != '' || $fields['password-confirmation'] != '') && $fields['password'] != $fields['password-confirmation']) { $this->_errors['password'] = $this->_errors['password-confirmation'] = __('Passwords did not match'); } elseif ($this->_Author->commit()) { $this->_Parent->Database->delete('tbl_forgotpass', " `expiry` < '" . DateTimeObj::getGMT('c') . "' OR `author_id` = '" . $author_id . "' "); if ($isOwner) { $this->_Parent->login($this->_Author->get('username'), $this->_Author->get('password'), true); } ## TODO: Fix me ### # Delegate: Edit # Description: After editing an author. ID of the author is provided. //$ExtensionManager->notifyMembers('Edit', getCurrentPage(), array('author_id' => $_REQUEST['id'])); redirect(URL . '/symphony/system/authors/edit/' . $author_id . '/saved/'); } else { $this->pageAlert(__('Unknown errors occurred while attempting to save. Please check your <a href="%s">activity log</a>.', array(URL . '/symphony/system/log/')), Alert::ERROR); } } } elseif (@array_key_exists('delete', $_POST['action'])) { ## TODO: Fix Me ### # Delegate: Delete # Description: Prior to deleting an author. ID is provided. //$ExtensionManager->notifyMembers('Delete', getCurrentPage(), array('author_id' => $author_id)); $this->_AuthorManager->delete($author_id); redirect(URL . '/symphony/system/authors/'); } }
public function processRawFieldData($data, &$status, &$message = null, $simulate = false, $entry_id = null) { $status = self::__OK__; $timestamp = null; // Prepopulate date if (is_null($data) || $data == '') { if ($this->get('pre_populate') != '') { $date = self::parseDate($this->get('pre_populate')); $date = $date['start']; $timestamp = $this->formatDate($date); } // Convert given date to timestamp } elseif ($status == self::__OK__ && DateTimeObj::validate($data)) { $timestamp = DateTimeObj::get('U', $data); } // Valid date if (!is_null($timestamp)) { return array('value' => DateTimeObj::get('c', $timestamp), 'date' => DateTimeObj::getGMT('Y-m-d H:i:s', $timestamp)); // Invalid date } else { return array('value' => null, 'date' => null); } }
public function getTimestamp() { return DateTimeObj::getGMT('Y-m-d H:i:s', time()); }
function action() { if (isset($_POST['action'])) { $actionParts = array_keys($_POST['action']); $action = end($actionParts); ##Login Attempted if ($action == 'login') { if (!isset($_POST['username']) || strlen(trim($_POST['username'])) == 0) { $this->invalid_credentials = true; $this->missing_username = true; } if (!isset($_POST['password']) || strlen(trim($_POST['password'])) == 0) { $this->invalid_credentials = true; $this->missing_password = true; } elseif (!Administration::instance()->login($_POST['username'], $_POST['password'])) { ## FIXME: Fix this delegate ### # Delegate: LoginFailure # Description: Failed login attempt. Username is provided. //Extension::notify('LoginFailure', getCurrentPage(), array('username' => $_POST['username'])); //$this->Body->appendChild(new XMLElement('p', 'Login invalid. <a href="'.ADMIN_URL . '/?forgot">Forgot your password?</a>')); //$this->_alert = 'Login invalid. <a href="'.ADMIN_URL . '/?forgot">Forgot your password?</a>'; $this->invalid_credentials = true; } else { ## FIXME: Fix this delegate ### # Delegate: LoginSuccess # Description: Successful login attempt. Username is provided. //Extension::notify('LoginSuccess', getCurrentPage(), array('username' => $_POST['username'])); if (isset($_POST['redirect'])) { redirect(URL . str_replace(parse_url(URL, PHP_URL_PATH), NULL, $_POST['redirect'])); } redirect(ADMIN_URL . '/'); } ##Reset of password requested } elseif ($action == 'reset') { $user = Symphony::Database()->query("SELECT id, email, first_name FROM `tbl_users` WHERE `email` = '%s'", array($_POST['email'])); if ($user->valid()) { $user = $user->current(); Symphony::Database()->delete('tbl_forgotpass', array(DateTimeObj::getGMT('c')), " `expiry` < '%s'"); $token = Symphony::Database()->query("\n\t\t\t\t\t\t\tSELECT\n\t\t\t\t\t\t\t\ttoken\n\t\t\t\t\t\t\tFROM\n\t\t\t\t\t\t\t\t`tbl_forgotpass`\n\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\texpiry > '%s'\n\t\t\t\t\t\t\tAND\n\t\t\t\t\t\t\t\tuser_id = %d\n\t\t\t\t\t\t\t", DateTimeObj::getGMT('c'), $user->id); if ($token->valid()) { $token = substr(md5(time() . rand(0, 200)), 0, 6); Symphony::Database()->insert('tbl_forgotpass', array('user_id' => $user->id, 'token' => $token, 'expiry' => DateTimeObj::getGMT('c', time() + 120 * 60))); } $this->_email_sent = General::sendEmail($user['email'], 'noreply@' . HTTP_HOST, __('Symphony Concierge'), __('New Symphony Account Password'), __('Hi %s,', array($user->first_name)) . PHP_EOL . __('A new password has been requested for your account. Login using the following link, and change your password via the Users area:') . PHP_EOL . PHP_EOL . ' ' . ADMIN_URL . "/login/{$token}/" . PHP_EOL . PHP_EOL . __('It will expire in 2 hours. If you did not ask for a new password, please disregard this email.') . PHP_EOL . PHP_EOL . __('Best Regards,') . PHP_EOL . __('The Symphony Team')); ## FIXME: Fix this delegate ### # Delegate: PasswordResetSuccess # Description: A successful password reset has taken place. User ID is provided //Extension::notify('PasswordResetSuccess', getCurrentPage(), array('user_id' => $user['id'])); } else { ## FIXME: Fix this delegate ### # Delegate: PasswordResetFailure # Description: A failed password reset has taken place. User ID is provided //Extension::notify('PasswordResetFailure', getCurrentPage(), array('user_id' => $user['id'])); $this->_email_sent = false; } ##Change of password requested } elseif ($action == 'change' && Administration::instance()->isLoggedIn()) { if (empty($_POST['password']) || empty($_POST['password-confirmation']) || $_POST['password'] != $_POST['password-confirmation']) { $this->_mismatchedPassword = true; } else { $user_id = Administration::instance()->User->id; $user = User::load($user_id); $user->set('password', md5(Symphony::Database()->escape($_POST['password']))); if (!User::save($user) || !Administration::instance()->login($user->username, $_POST['password'])) { redirect(URL . "symphony/system/users/edit/{$user_id}/error/"); } ## FIXME: Fix this delegate ### # Delegate: PasswordChanged # Description: After editing an User. ID of the User is provided. //Extension::notify('PasswordChanged', getCurrentPage(), array('user_id' => $user_id)); redirect(ADMIN_URL . '/'); } } } elseif ($_REQUEST['action'] == 'resetpass' && isset($_REQUEST['token'])) { $user = Symphony::Database()->query("\n\t\t\t\t\t\tSELECT\n\t\t\t\t\t\t\tu.id, u.email, u.first_name\n\t\t\t\t\t\tFROM\n\t\t\t\t\t\t\t`tbl_users` as u, `tbl_forgotpass` as t2\n\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\tt2.`token` = '%s'\n\t\t\t\t\t\tAND\n\t\t\t\t\t\t\tu.`id` = t2.`user_id`\n\t\t\t\t\t\tLIMIT 1\n\t\t\t\t\t", $_REQUEST['token']); if ($user->valid()) { $user = $user->current(); $newpass = General::generatePassword(); General::sendEmail($user->email, 'noreply@' . HTTP_HOST, 'Symphony Concierge', 'RE: New Symphony Account Password', 'Hi ' . $user['first_name'] . ',' . PHP_EOL . "As requested, here is your new Symphony User Password for '" . URL . "'" . PHP_EOL . "\t{$newpass}" . PHP_EOL . PHP_EOL . 'Best Regards,' . PHP_EOL . 'The Symphony Team'); Symphony::Database()->update('tbl_users', array('password' => md5($newpass)), array($user->id), "`id` = '%d'"); Symphony::Database()->delete('tbl_forgotpass', array($user->id), " `user_id` = '%d'"); ## FIXME: Fix this delegate ### # Delegate: PasswordResetRequest # Description: User has requested a password reset. User ID is provided. //Extension::notify('PasswordResetRequest', getCurrentPage(), array('user_id' => $user['id'])); $this->_alert = 'Password reset. Check your email'; } } }
public function __formAction() { $fields = $_POST['fields']; $this->_errors = array(); $providers = Symphony::ExtensionManager()->getProvidersOf(iProvider::EVENT); $providerClass = null; if (trim($fields['name']) == '') { $this->_errors['name'] = __('This is a required field'); } if (trim($fields['source']) == '') { $this->_errors['source'] = __('This is a required field'); } $filters = isset($fields['filters']) ? $fields['filters'] : array(); // See if a Provided Datasource is saved if (!empty($providers)) { foreach ($providers as $providerClass => $provider) { if ($fields['source'] == call_user_func(array($providerClass, 'getSource'))) { call_user_func_array(array($providerClass, 'validate'), array(&$fields, &$this->_errors)); break; } unset($providerClass); } } $classname = Lang::createHandle($fields['name'], 255, '_', false, true, array('@^[^a-z\\d]+@i' => '', '/[^\\w-\\.]/i' => '')); $rootelement = str_replace('_', '-', $classname); $extends = 'SectionEvent'; // Check to make sure the classname is not empty after handlisation. if (empty($classname) && !isset($this->_errors['name'])) { $this->_errors['name'] = __('Please ensure name contains at least one Latin-based character.', array($classname)); } $file = EVENTS . '/event.' . $classname . '.php'; $isDuplicate = false; $queueForDeletion = null; if ($this->_context[0] == 'new' && is_file($file)) { $isDuplicate = true; } elseif ($this->_context[0] == 'edit') { $existing_handle = $this->_context[1]; if ($classname != $existing_handle && is_file($file)) { $isDuplicate = true; } elseif ($classname != $existing_handle) { $queueForDeletion = EVENTS . '/event.' . $existing_handle . '.php'; } } // Duplicate if ($isDuplicate) { $this->_errors['name'] = __('An Event with the name %s already exists', array('<code>' . $classname . '</code>')); } if (empty($this->_errors)) { $multiple = in_array('expect-multiple', $filters); $elements = null; $placeholder = '<!-- GRAB -->'; $source = $fields['source']; $params = array('rootelement' => $rootelement); $about = array('name' => $fields['name'], 'version' => 'Symphony ' . Symphony::Configuration()->get('version', 'symphony'), 'release date' => DateTimeObj::getGMT('c'), 'author name' => Symphony::Author()->getFullName(), 'author website' => URL, 'author email' => Symphony::Author()->get('email')); // If there is a provider, get their template if ($providerClass) { $eventShell = file_get_contents(call_user_func(array($providerClass, 'getTemplate'))); } else { $eventShell = file_get_contents($this->getTemplate('blueprints.event')); $about['trigger condition'] = $rootelement; } $this->__injectAboutInformation($eventShell, $about); // Replace the name $eventShell = str_replace('<!-- CLASS NAME -->', $classname, $eventShell); // Build the templates if ($providerClass) { $eventShell = call_user_func(array($providerClass, 'prepare'), $fields, $params, $eventShell); } else { $this->__injectFilters($eventShell, $filters); // Add Documentation require_once CONTENT . '/content.ajaxeventdocumentation.php'; $ajaxEventDoc = new contentAjaxEventDocumentation(); $documentation = null; $doc_parts = array(); // Add Documentation (Success/Failure) $ajaxEventDoc->addEntrySuccessDoc($doc_parts, $rootelement, $fields['source'], $filters); $ajaxEventDoc->addEntryFailureDoc($doc_parts, $rootelement, $fields['source'], $filters); // Filters $ajaxEventDoc->addDefaultFiltersDoc($doc_parts, $rootelement, $fields['source'], $filters); // Frontend Markup $ajaxEventDoc->addFrontendMarkupDoc($doc_parts, $rootelement, $fields['source'], $filters); $ajaxEventDoc->addSendMailFilterDoc($doc_parts, $rootelement, $fields['source'], $filters); /** * Allows adding documentation for new filters. A reference to the $documentation * array is provided, along with selected filters * @delegate AppendEventFilterDocumentation * @param string $context * '/blueprints/events/(edit|new|info)/' * @param array $selected * An array of all the selected filters for this Event * @param array $documentation * An array of all the documentation XMLElements, passed by reference */ Symphony::ExtensionManager()->notifyMembers('AppendEventFilterDocumentation', '/blueprints/events/' . $rootelement . '/', array('selected' => $filters, 'documentation' => &$doc_parts)); $documentation = join(PHP_EOL, array_map(create_function('$x', 'return rtrim($x->generate(true, 4));'), $doc_parts)); $documentation = str_replace('\'', '\\\'', $documentation); $eventShell = str_replace('<!-- CLASS EXTENDS -->', $extends, $eventShell); $eventShell = str_replace('<!-- DOCUMENTATION -->', General::tabsToSpaces($documentation, 4), $eventShell); } $eventShell = str_replace('<!-- ROOT ELEMENT -->', $rootelement, $eventShell); $eventShell = str_replace('<!-- CLASS NAME -->', $classname, $eventShell); $eventShell = str_replace('<!-- SOURCE -->', $source, $eventShell); // Remove left over placeholders $eventShell = preg_replace(array('/<!--[\\w ]++-->/'), '', $eventShell); if ($this->_context[0] == 'new') { /** * Prior to creating an Event, the file path where it will be written to * is provided and well as the contents of that file. * * @delegate EventsPreCreate * @since Symphony 2.2 * @param string $context * '/blueprints/events/' * @param string $file * The path to the Event file * @param string $contents * The contents for this Event as a string passed by reference * @param array $filters * An array of the filters attached to this event */ Symphony::ExtensionManager()->notifyMembers('EventPreCreate', '/blueprints/events/', array('file' => $file, 'contents' => &$eventShell, 'filters' => $filters)); } else { /** * Prior to editing an Event, the file path where it will be written to * is provided and well as the contents of that file. * * @delegate EventPreEdit * @since Symphony 2.2 * @param string $context * '/blueprints/events/' * @param string $file * The path to the Event file * @param string $contents * The contents for this Event as a string passed by reference * @param array $filters * An array of the filters attached to this event */ Symphony::ExtensionManager()->notifyMembers('EventPreEdit', '/blueprints/events/', array('file' => $file, 'contents' => &$eventShell, 'filters' => $filters)); } // Write the file if (!is_writable(dirname($file)) || !($write = General::writeFile($file, $eventShell, Symphony::Configuration()->get('write_mode', 'file')))) { $this->pageAlert(__('Failed to write Event to disk.') . ' ' . __('Please check permissions on %s.', array('<code>/workspace/events</code>')), Alert::ERROR); // Write successful } else { if (function_exists('opcache_invalidate')) { opcache_invalidate($file, true); } // Attach this event to pages $connections = $fields['connections']; ResourceManager::setPages(RESOURCE_TYPE_EVENT, is_null($existing_handle) ? $classname : $existing_handle, $connections); if ($queueForDeletion) { General::deleteFile($queueForDeletion); $pages = PageManager::fetch(false, array('events', 'id'), array("\n `events` REGEXP '[[:<:]]" . $existing_handle . "[[:>:]]'\n ")); if (is_array($pages) && !empty($pages)) { foreach ($pages as $page) { $page['events'] = preg_replace('/\\b' . $existing_handle . '\\b/i', $classname, $page['events']); PageManager::edit($page['id'], $page); } } } if ($this->_context[0] == 'new') { /** * After creating the Event, the path to the Event file is provided * * @delegate EventPostCreate * @since Symphony 2.2 * @param string $context * '/blueprints/events/' * @param string $file * The path to the Event file */ Symphony::ExtensionManager()->notifyMembers('EventPostCreate', '/blueprints/events/', array('file' => $file)); } else { /** * After editing the Event, the path to the Event file is provided * * @delegate EventPostEdit * @since Symphony 2.2 * @param string $context * '/blueprints/events/' * @param string $file * The path to the Event file * @param string $previous_file * The path of the previous Event file in the case where an Event may * have been renamed. To get the handle from this value, see * `EventManager::__getHandleFromFilename` */ Symphony::ExtensionManager()->notifyMembers('EventPostEdit', '/blueprints/events/', array('file' => $file, 'previous_file' => $queueForDeletion ? $queueForDeletion : null)); } redirect(SYMPHONY_URL . '/blueprints/events/edit/' . $classname . '/' . ($this->_context[0] == 'new' ? 'created' : 'saved') . '/'); } } }
public function __actionNew() { if (array_key_exists('save', $_POST['action']) || array_key_exists("done", $_POST['action'])) { $sectionManager = new SectionManager($this->_Parent); $section_id = $sectionManager->fetchIDFromHandle($this->_context['section_handle']); if (!($section = $sectionManager->fetch($section_id))) { Administration::instance()->customError(__('Unknown Section'), __('The Section you are looking, <code>%s</code> for could not be found.', $this->_context['section_handle'])); } $entryManager = new EntryManager($this->_Parent); $entry =& $entryManager->create(); $entry->set('section_id', $section_id); $entry->set('author_id', Administration::instance()->Author->get('id')); $entry->set('creation_date', DateTimeObj::get('Y-m-d H:i:s')); $entry->set('creation_date_gmt', DateTimeObj::getGMT('Y-m-d H:i:s')); $fields = $_POST['fields']; ## Combine FILES and POST arrays, indexed by their custom field handles if (isset($_FILES['fields'])) { $filedata = General::processFilePostData($_FILES['fields']); foreach ($filedata as $handle => $data) { if (!isset($fields[$handle])) { $fields[$handle] = $data; } elseif (isset($data['error']) && $data['error'] == 4) { $fields['handle'] = NULL; } else { foreach ($data as $ii => $d) { if (isset($d['error']) && $d['error'] == 4) { $fields[$handle][$ii] = NULL; } elseif (is_array($d) && !empty($d)) { foreach ($d as $key => $val) { $fields[$handle][$ii][$key] = $val; } } } } } } if (__ENTRY_FIELD_ERROR__ == $entry->checkPostData($fields, $this->_errors)) { $this->pageAlert(__('Some errors were encountered while attempting to save.'), Alert::ERROR); } elseif (__ENTRY_OK__ != $entry->setDataFromPost($fields, $error)) { $this->pageAlert($error['message'], Alert::ERROR); } else { /** * Just prior to creation of an Entry * * @delegate EntryPreCreate * @param string $context * '/publish/new/' * @param Section $section * @param Entry $entry * @param array $fields */ Symphony::ExtensionManager()->notifyMembers('EntryPreCreate', '/publish/new/', array('section' => $section, 'entry' => &$entry, 'fields' => &$fields)); if (!$entry->commit()) { define_safe('__SYM_DB_INSERT_FAILED__', true); $this->pageAlert(NULL, Alert::ERROR); } else { /** * Creation of an Entry. New Entry object is provided. * * @delegate EntryPostCreate * @param string $context * '/publish/new/' * @param Section $section * @param Entry $entry * @param array $fields */ Symphony::ExtensionManager()->notifyMembers('EntryPostCreate', '/publish/new/', array('section' => $section, 'entry' => $entry, 'fields' => $fields)); $prepopulate_field_id = $prepopulate_value = NULL; if (isset($_POST['prepopulate'])) { $prepopulate_field_id = array_shift(array_keys($_POST['prepopulate'])); $prepopulate_value = stripslashes(rawurldecode(array_shift($_POST['prepopulate']))); } redirect(sprintf('%s/publish/%s/edit/%d/created%s/', SYMPHONY_URL, $this->_context['section_handle'], $entry->get('id'), !is_null($prepopulate_field_id) ? ":{$prepopulate_field_id}:{$prepopulate_value}" : NULL)); } } } }
function __formAction() { $fields = $_POST['fields']; $this->_errors = array(); if (trim($fields['name']) == '') { $this->_errors['name'] = __('This is a required field'); } if ($fields['source'] == 'static_xml') { if (trim($fields['static_xml']) == '') { $this->_errors['static_xml'] = __('This is a required field'); } else { $xml_errors = NULL; include_once TOOLKIT . '/class.xsltprocess.php'; General::validateXML($fields['static_xml'], $xml_errors, false, new XsltProcess()); if (!empty($xml_errors)) { $this->_errors['static_xml'] = __('XML is invalid'); } } } elseif ($fields['source'] == 'dynamic_xml') { if (trim($fields['dynamic_xml']['url']) == '') { $this->_errors['dynamic_xml']['url'] = __('This is a required field'); } if (trim($fields['dynamic_xml']['xpath']) == '') { $this->_errors['dynamic_xml']['xpath'] = __('This is a required field'); } if (!is_numeric($fields['dynamic_xml']['cache'])) { $this->_errors['dynamic_xml']['cache'] = __('Must be a valid number'); } elseif ($fields['dynamic_xml']['cache'] < 1) { $this->_errors['dynamic_xml']['cache'] = __('Must be greater than zero'); } } else { if ($fields['source'] != 'navigation') { if (strlen(trim($fields['max_records'])) == 0 || is_numeric($fields['max_records']) && $fields['max_records'] < 1) { $this->_errors['max_records'] = __('A result limit must be set'); } elseif (!self::__isValidPageString($fields['max_records'])) { $this->_errors['max_records'] = __('Must be a valid number or parameter'); } if (strlen(trim($fields['page_number'])) == 0 || is_numeric($fields['page_number']) && $fields['page_number'] < 1) { $this->_errors['page_number'] = __('A page number must be set'); } elseif (!self::__isValidPageString($fields['page_number'])) { $this->_errors['page_number'] = __('Must be a valid number or parameter'); } } } $classname = Lang::createHandle($fields['name'], NULL, '_', false, true, array('@^[^a-z]+@i' => '', '/[^\\w-\\.]/i' => '')); $rootelement = str_replace('_', '-', $classname); $file = DATASOURCES . '/data.' . $classname . '.php'; $isDuplicate = false; $queueForDeletion = NULL; if ($this->_context[0] == 'new' && @is_file($file)) { $isDuplicate = true; } elseif ($this->_context[0] == 'edit') { $existing_handle = $this->_context[1]; if ($classname != $existing_handle && @is_file($file)) { $isDuplicate = true; } elseif ($classname != $existing_handle) { $queueForDeletion = DATASOURCES . '/data.' . $existing_handle . '.php'; } } ##Duplicate if ($isDuplicate) { $this->_errors['name'] = __('A Data source with the name <code>%s</code> name already exists', array($classname)); } if (empty($this->_errors)) { $dsShell = file_get_contents(TEMPLATE . '/datasource.tpl'); //$oDate = $this->_Parent->getDateObj(); $params = array('rootelement' => $rootelement); $about = array('name' => $fields['name'], 'version' => '1.0', 'release date' => DateTimeObj::getGMT('c'), 'author name' => $this->_Parent->Author->getFullName(), 'author website' => URL, 'author email' => $this->_Parent->Author->get('email')); $source = $fields['source']; $filter = NULL; $elements = NULL; switch ($source) { case 'authors': $filters = $fields['filter']['author']; $elements = $fields['xml_elements']; $params['order'] = $fields['order']; $params['limit'] = $fields['max_records']; $params['redirectonempty'] = isset($fields['redirect_on_empty']) ? 'yes' : 'no'; $params['requiredparam'] = $fields['required_url_param']; $params['paramoutput'] = $fields['param']; $params['sort'] = $fields['sort']; $params['startpage'] = $fields['page_number']; $dsShell = str_replace('<!-- GRAB -->', "include(TOOLKIT . '/data-sources/datasource.author.php');", $dsShell); break; case 'navigation': $filters = $fields['filter']['navigation']; $params['order'] = $fields['order']; $params['redirectonempty'] = isset($fields['redirect_on_empty']) ? 'yes' : 'no'; $params['requiredparam'] = $fields['required_url_param']; $dsShell = str_replace('<!-- GRAB -->', "include(TOOLKIT . '/data-sources/datasource.navigation.php');", $dsShell); break; case 'dynamic_xml': $namespaces = $fields['dynamic_xml']['namespace']; $filters = array(); for ($ii = 0; $ii < count($namespaces['name']); $ii++) { $filters[$namespaces['name'][$ii]] = $namespaces['uri'][$ii]; } $params['url'] = $fields['dynamic_xml']['url']; $params['xpath'] = $fields['dynamic_xml']['xpath']; $params['cache'] = $fields['dynamic_xml']['cache']; $dsShell = str_replace('<!-- GRAB -->', "include(TOOLKIT . '/data-sources/datasource.dynamic_xml.php');", $dsShell); break; case 'static_xml': $value = sprintf('$result = "%s";', addslashes($fields['static_xml'])); $dsShell = str_replace('<!-- GRAB -->', $value, $dsShell); break; default: $elements = $fields['xml_elements']; if (is_array($fields['filter']) && !empty($fields['filter'])) { $filters = array(); foreach ($fields['filter'] as $f) { foreach ($f as $key => $val) { $filters[$key] = $val; } } } $params['order'] = $fields['order']; $params['group'] = $fields['group']; $params['limit'] = $fields['max_records']; $params['redirectonempty'] = isset($fields['redirect_on_empty']) ? 'yes' : 'no'; $params['requiredparam'] = $fields['required_url_param']; $params['paramoutput'] = $fields['param']; $params['sort'] = $fields['sort']; $params['startpage'] = $fields['page_number']; $params['htmlencode'] = $fields['html_encode']; $dsShell = str_replace('<!-- GRAB -->', "include(TOOLKIT . '/data-sources/datasource.section.php');", $dsShell); break; } $this->__injectVarList($dsShell, $params); $this->__injectAboutInformation($dsShell, $about); $this->__injectIncludedElements($dsShell, $elements); $this->__injectFilters($dsShell, $filters); $dsShell = str_replace('<!-- CLASS NAME -->', $classname, $dsShell); $dsShell = str_replace('<!-- SOURCE -->', $source, $dsShell); if (preg_match_all('@{(\\$ds-[^}]+)}@i', $dsShell, $matches)) { $dependancies = array(); foreach ($matches[1] as $match) { if (preg_match_all('/(\\$ds-[^:]+)/i', $match, $inner_matches)) { $dependancies = array_merge($dependancies, $inner_matches[1]); } } $dependancies = General::array_remove_duplicates($dependancies); $dsShell = str_replace('<!-- DS DEPENDANCY LIST -->', "'" . implode("', '", $dependancies) . "'", $dsShell); } ## Remove left over placeholders $dsShell = preg_replace(array('/<!--[\\w ]++-->/', '/(\\r\\n){2,}/', '/(\\t+[\\r\\n]){2,}/'), '', $dsShell); ##Write the file if (!is_writable(dirname($file)) || !($write = General::writeFile($file, $dsShell, $this->_Parent->Configuration->get('write_mode', 'file')))) { $this->pageAlert(__('Failed to write Data source to <code>%s</code>. Please check permissions.', array(DATASOURCES)), Alert::ERROR); } else { if ($queueForDeletion) { General::deleteFile($queueForDeletion); ## Update pages that use this DS $sql = "SELECT * FROM `tbl_pages` WHERE `data_sources` REGEXP '[[:<:]]" . $existing_handle . "[[:>:]]' "; $pages = $this->_Parent->Database->fetch($sql); if (is_array($pages) && !empty($pages)) { foreach ($pages as $page) { $page['data_sources'] = preg_replace('/\\b' . $existing_handle . '\\b/i', $classname, $page['data_sources']); $this->_Parent->Database->update($page, 'tbl_pages', "`id` = '" . $page['id'] . "'"); } } } ### TODO: Fix me ### # Delegate: Create # Description: After saving the datasource, the file path is provided and an array # of variables set by the editor #$ExtensionManager->notifyMembers('Create', getCurrentPage(), array('file' => $file, 'defines' => $defines, 'var' => $var)); redirect(URL . '/symphony/blueprints/datasources/edit/' . $classname . '/' . ($this->_context[0] == 'new' ? 'created' : 'saved') . '/'); } } }
public function __actionEdit() { if (!($author_id = $this->_context[1])) { redirect(SYMPHONY_URL . '/system/authors/'); } $isOwner = $author_id == Administration::instance()->Author->get('id'); if (@array_key_exists('save', $_POST['action']) || @array_key_exists('done', $_POST['action'])) { $fields = $_POST['fields']; $this->_Author = AuthorManager::fetchByID($author_id); $authenticated = false; if ($fields['email'] != $this->_Author->get('email')) { $changing_email = true; } // Check the old password was correct if (isset($fields['old-password']) && strlen(trim($fields['old-password'])) > 0 && General::hash(trim($fields['old-password'])) == $this->_Author->get('password')) { $authenticated = true; } else { if (Administration::instance()->Author->isDeveloper()) { $authenticated = true; } } $this->_Author->set('id', $author_id); if ($this->_Author->isPrimaryAccount() || $isOwner && Administration::instance()->Author->isDeveloper()) { $this->_Author->set('user_type', 'developer'); // Primary accounts are always developer, Developers can't lower their level } elseif (Administration::instance()->Author->isDeveloper() && isset($fields['user_type'])) { $this->_Author->set('user_type', $fields['user_type']); // Only developer can change user type } $this->_Author->set('email', $fields['email']); $this->_Author->set('username', $fields['username']); $this->_Author->set('first_name', General::sanitize($fields['first_name'])); $this->_Author->set('last_name', General::sanitize($fields['last_name'])); $this->_Author->set('language', $fields['language']); if (trim($fields['password']) != '') { $this->_Author->set('password', General::hash($fields['password'])); $changing_password = true; } // Don't allow authors to set the Section Index as a default area // If they had it previously set, just save `null` which will redirect // the Author (when logging in) to their own Author record if ($this->_Author->get('user_type') == 'author' && $fields['default_area'] == '/blueprints/sections/') { $this->_Author->set('default_area', null); } else { $this->_Author->set('default_area', $fields['default_area']); } $this->_Author->set('auth_token_active', $fields['auth_token_active'] ? $fields['auth_token_active'] : 'no'); if ($this->_Author->validate($this->_errors)) { if (!$authenticated && ($changing_password || $changing_email)) { if ($changing_password) { $this->_errors['old-password'] = __('Wrong password. Enter old password to change it.'); } elseif ($changing_email) { $this->_errors['old-password'] = __('Wrong password. Enter old one to change email address.'); } } elseif (($fields['password'] != '' || $fields['password-confirmation'] != '') && $fields['password'] != $fields['password-confirmation']) { $this->_errors['password'] = $this->_errors['password-confirmation'] = __('Passwords did not match'); } elseif ($this->_Author->commit()) { Symphony::Database()->delete('tbl_forgotpass', " `expiry` < '" . DateTimeObj::getGMT('c') . "' OR `author_id` = '" . $author_id . "' "); if ($isOwner) { Administration::instance()->login($this->_Author->get('username'), $this->_Author->get('password'), true); } /** * After editing an author, provided with the Author object * * @delegate AuthorPostEdit * @since Symphony 2.2 * @param string $context * '/system/authors/' * @param Author $author * An Author object */ Symphony::ExtensionManager()->notifyMembers('AuthorPostEdit', '/system/authors/', array('author' => $this->_Author)); redirect(SYMPHONY_URL . '/system/authors/edit/' . $author_id . '/saved/'); } else { $this->pageAlert(__('Unknown errors occurred while attempting to save.') . '<a href="' . SYMPHONY_URL . '/system/log/">' . __('Check your activity log') . '</a>.', Alert::ERROR); } } else { if (is_array($this->_errors) && !empty($this->_errors)) { $this->pageAlert(__('There were some problems while attempting to save. Please check below for problem fields.'), Alert::ERROR); } } } else { if (@array_key_exists('delete', $_POST['action'])) { /** * Prior to deleting an author, provided with the Author ID. * * @delegate AuthorPreDelete * @since Symphony 2.2 * @param string $context * '/system/authors/' * @param integer $author_id * The ID of Author ID that is about to be deleted */ Symphony::ExtensionManager()->notifyMembers('AuthorPreDelete', '/system/authors/', array('author_id' => $author_id)); if (!$isOwner) { AuthorManager::delete($author_id); redirect(SYMPHONY_URL . '/system/authors/'); } else { $this->pageAlert(__('You cannot remove yourself as you are the active Author.'), Alert::ERROR); } } } }
public function processData($data, Entry $entry = NULL) { if (isset($entry->data()->{$this->{'element-name'}})) { $result = $entry->data()->{$this->{'element-name'}}; } else { $result = (object) array('value' => null); } if (is_null($data) || strlen(trim($data)) == 0) { $result->value = NULL; if ($this->{'pre-populate'} == 'yes') { $timestamp = strtotime(DateTimeObj::get('c', null)); } } else { $timestamp = strtotime($data); } if (!is_null($timestamp) && $timestamp !== false) { $result->value = DateTimeObj::getGMT('Y-m-d H:i:s', $timestamp); } else { $result->value = $data; } return $result; }
public function processRawFieldData($data, &$status, &$message = null, $simulate = false, $entry_id = null) { $status = self::__OK__; $timestamp = null; // Prepopulate date if (is_null($data) || $data == '') { if ($this->get('pre_populate') == 'yes') { $timestamp = time(); } } else { if ($status == self::__OK__ && DateTimeObj::validate($data)) { $timestamp = DateTimeObj::get('U', $data); } } // Valid date if (!is_null($timestamp)) { return array('value' => DateTimeObj::get('c', $timestamp), 'date' => DateTimeObj::getGMT('Y-m-d H:i:s', $timestamp)); } else { return array('value' => null, 'date' => null); } }