protected static function handleRequest(\Curry_Request $request) { ob_start(); $app = \Curry_Application::getInstance(); $app->handle($request); return ob_get_clean(); }
public function show(Curry_Backend $backend, $params = null) { if ($params === null) { $params = $_GET; } try { /*if (isAjax()) $pr = Curry_URL::setPreventRedirect(true);*/ $action = isset($params['action']) ? explode(".", $params['action']) : array(); $this->dispatch($action, $backend, $params); /*if (isAjax()) Curry_URL::setPreventRedirect($pr);*/ } catch (Curry_Exception_RedirectPrevented $e) { Curry_Application::returnPartial('<script type="text/javascript">window.location.href = "' . addcslashes($e->getUrl(), '"') . '";</script>'); } }
/** * Edit file view. * * @throws Exception */ public function showEdit() { $files = self::getFileList(); $file = $_GET['file']; if (!isset($files[$file])) { throw new Exception('File not found'); } $file = $files[$file]; $form = $this->getEditForm($file); if (isPost()) { $ajax = array('success' => 1); if ($form->isValid($_POST)) { // Save content and preserve EOL style $values = $form->getValues(); $code = $values['content']; $eol = Curry_Util::getStringEol($code); $targetEol = urldecode($values['eol']); if ($eol !== $targetEol) { $code = str_replace($eol, $targetEol, $code); } file_put_contents($file->getPathname(), $code); $form = $this->getEditForm($file); } else { $error = "Validation error!"; foreach ($form->getMessages() as $element => $messages) { $error .= "\n{$element}: " . join(', ', $messages); } $ajax['success'] = 0; $ajax['error'] = $error; } if ($_POST['_ajaxsubmit']) { $form->render(); // fixes issue with csrf-token $ajax['values'] = $form->getValues(); Curry_Application::returnJson($ajax); } } Curry_Admin::getInstance()->addBodyClass('tpl-fullscreen'); Curry_Admin::getInstance()->addBodyClass('tpl-fileeditor'); $this->addMenu($_GET['file']); $this->addMainContent($form); }
/** * Return partial html-content to browser and exit. Will set content-type header and return the content. * * @deprecated Use Curry_Application::returnPartial() instead. * @param mixed $content */ public function returnPartial($content) { Curry_Application::returnPartial($content); }
/** * Generate TinyMCE link list. */ public function showTinyMceList() { $pages = array(); foreach (PageQuery::create()->orderByBranch()->find() as $page) { if (self::isTemplatePage($page)) { continue; } $pages[] = array(str_repeat(Curry_Core::SELECT_TREE_PREFIX, $page->getLevel()) . $page->getName(), $page->getUrl()); } Curry_Application::returnPartial('var tinyMCELinkList = ' . json_encode($pages) . ';', "text/plain"); }
/** {@inheritdoc} */ public function showMain() { $rootPage = PageQuery::create()->findRoot(); $code = Curry_Backend_PageSyncHelper::getPageCode($rootPage); $localChecksum = sha1(serialize($code)); if (isPost('fetch')) { Curry_Application::returnJson($code); } $form = new Curry_Form(array('csrfCheck' => false, 'action' => (string) url('', $_GET), 'method' => 'post', 'elements' => array('url' => array('text', array('label' => 'URL', 'placeholder' => 'http://example.com/admin.php', 'value' => isset($_COOKIE['curry:remote_url']) ? $_COOKIE['curry:remote_url'] : '')), 'user' => array('text', array('label' => 'User', 'value' => isset($_COOKIE['curry:remote_user']) ? $_COOKIE['curry:remote_user'] : '******')), 'password' => array('password', array('label' => 'Password', 'value' => '')), 'submit' => array('submit', array('class' => 'btn btn-primary', 'label' => 'Fetch'))))); if (isPost('code')) { // we have page-code if ($localChecksum !== $_POST['local_checksum']) { throw new Exception('Local pages were changed during synchronization process, aborting!'); } $remoteCode = json_decode($_POST['code'], true); // Update selected pages if (isset($_POST['page'])) { $updatedPages = Curry_Backend_PageSyncHelper::restorePages($rootPage, $remoteCode, array_keys($_POST['page'])); $this->addMessage(count($updatedPages) . ' pages updated!', self::MSG_SUCCESS); } // Delete selected pages if (isset($_POST['delete'])) { $pagesToDelete = array_keys($_POST['delete']); foreach ($pagesToDelete as $pageId) { $page = PageQuery::create()->findPk($pageId); if (!$page) { throw new Exception('Unable to find page to delete.'); } if (!$page->isLeaf()) { $this->addMessage('Unable to delete page "' . $page->getName() . '" because it has subpages.', self::MSG_ERROR); continue; } $dependantPages = $page->getDependantPages(); if (count($dependantPages)) { $this->addMessage('Unable to delete page "' . $page->getName() . '" because other pages depend on it.', self::MSG_ERROR); continue; } $page->delete(); $this->addMessage('Deleted page "' . $page->getName() . '"', self::MSG_WARNING); } } } else { if (isPost() && $form->isValid($_POST)) { // have user/password try { $context = stream_context_create(array('http' => array('method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => http_build_query(array('login_username' => $form->user->getValue(), 'login_password' => $form->password->getValue(), 'fetch' => '1'))))); $remote = (string) url($form->url->getValue(), array('module' => 'Curry_Backend_PageSync')); $remoteResponse = file_get_contents($remote, null, $context); if ($remoteResponse === false) { throw new Exception('Invalid response'); } $remoteCode = json_decode($remoteResponse, true); if ($remoteCode === null) { throw new Exception('Invalid json: ' . $remoteResponse); } setcookie('curry:remote_url', $form->url->getValue(), time() + 86400 * 365); setcookie('curry:remote_user', $form->user->getValue(), time() + 86400 * 365); $this->addMainContent('<form action="' . url('', $_GET) . '" method="post" class="well">'); $this->addMainContent('<input type="hidden" name="code" value="' . htmlspecialchars($remoteResponse) . '" />'); $this->addMainContent('<input type="hidden" name="local_checksum" value="' . htmlspecialchars($localChecksum) . '" />'); $this->addMainContent('<ul>'); $this->comparePageCode($code, $remoteCode); $this->addMainContent('</ul>'); $this->addMainContent('<button type="submit" class="btn btn-primary">Sync</button>'); $this->addMainContent('</form>'); } catch (Exception $e) { $this->addMainContent($form); $this->addMessage($e->getMessage(), self::MSG_ERROR); } } else { $this->addMainContent(self::INTRO); $this->addMainContent($form); } } }
/** * Cast to string, return HTML or JSON. * * @return string */ public function __toString() { try { if (isset($_GET['json'])) { Curry_Application::returnJson($this->getJson()); } else { return $this->getHtml(); } } catch (Exception $e) { return $e->getMessage(); } return ''; }
/** * Register a function for background execution on shutdown. * Output is not possible in the callback function. * * @param callback $callback * @param mixed $parameters,... [optional] Optional parameters passed to the callback function. */ public static function registerBackgroundFunction($callback) { if (self::$backgroundFunctions === null) { // Replace output-buffering with custom function while (ob_get_level()) { ob_end_clean(); } ob_start(function ($buffer) { header("Connection: close", true); header("Content-Encoding: none", true); header("Content-Length: " . strlen($buffer), true); return $buffer; }); register_shutdown_function(array(__CLASS__, 'executeBackgroundFunctions')); self::$backgroundFunctions = array(); } self::$backgroundFunctions[] = func_get_args(); }
/** * Render a page and return content. * * @param array $vars * @param array $options * @return string */ public function render(array $vars = array(), array $options = array()) { $twig = Curry_Twig_Template::getSharedEnvironment(); // Todo: Rename curry to app? $appVars = Curry_Application::getInstance()->getGlobalVariables(); if (isset($vars['curry'])) { Curry_Array::extend($appVars, $vars['curry']); } $vars['curry'] = Curry_Array::extend($appVars, $this->getGlobals()); foreach ($vars as $k => $v) { $twig->addGlobal($k, $v); } $moduleContent = $this->generate($options); if (isset($options['pageModuleId'])) { $pageModuleId = $options['pageModuleId']; $pageModuleWrappers = $this->getPageModuleWrappers(); if (isset($pageModuleWrappers[$pageModuleId])) { $pageModuleWrapper = $pageModuleWrappers[$pageModuleId]; return $moduleContent[$pageModuleWrapper->getTarget()]; } else { throw new Exception('PageModule with id = ' . $pageModuleId . ' not found on page.'); } } $template = $this->getTemplateObject(); return $this->renderTemplate($template, $moduleContent); }
/** * Backup database. */ public function showBackup() { $this->showMainMenu(); $tables = array(); $selectedTables = array(); foreach (Curry_Propel::getModels() as $package => $classes) { $selectedTables = array_merge($selectedTables, array_values($classes)); $tables[$package] = array(); foreach ($classes as $table) { $tables[$package][$table] = $table; } } $form = new Curry_Form(array('action' => url('', array("module", "view", "page_id")), 'method' => 'post', 'elements' => array('tables' => array('multiselect', array('label' => 'Tables', 'multiOptions' => $tables, 'value' => $selectedTables, 'size' => 15)), 'name' => array('text', array('label' => 'Name', 'required' => true, 'value' => 'backup_%Y-%m-%d_%H-%M-%S.txt', 'description' => 'Name of the file, strftime() is used to format the string.')), 'type' => array('radio', array('label' => 'Where do you want to save?', 'multiOptions' => array('online' => 'Save online', 'local' => 'Save to local file'), 'value' => 'online'))))); $form->addElement('submit', 'Go'); if (isPost() && ($_POST['tables'] == '*' || $_POST['tables'] == array('*'))) { $_POST['tables'] = $selectedTables; } if (isPost() && $form->isValid($_POST)) { $values = $form->getValues(); if ($values['type'] == 'local') { // dump to temp, stream to client $fp = fopen("php://temp", 'r+'); Curry_Backend_DatabaseHelper::dumpDatabase($fp, $values['tables'], $this); rewind($fp); $name = Curry_String::getRewriteString(Curry_Core::$config->curry->name) . '-db.txt'; Curry_Application::returnData($fp, 'application/octet-stream', $name); } else { if ($values['type'] == 'online') { $filename = Curry_Backend_DatabaseHelper::createBackupName($values['name']); $status = Curry_Backend_DatabaseHelper::dumpDatabase($filename, $values['tables'], $this); $this->addMessage('Backup created ' . $filename, $status ? self::MSG_SUCCESS : self::MSG_ERROR); } } } $this->addMainContent($form); }
/** * Download file. */ public function showDownload() { $paths = (array) $_GET['path']; $zip = count($paths) > 1; $physicals = array(); foreach ($paths as $path) { $physical = self::virtualToPhysical($path); $physicals[] = $physical; if (is_dir($physical)) { $zip = true; } } $name = 'files.zip'; if (count($physicals) === 1) { $name = basename($physicals[0]) . ($zip ? '.zip' : ''); } if ($zip) { require_once 'pclzip/pclzip.lib.php'; $tempfile = tempnam(Curry_Core::$config->curry->tempPath, "curry-download"); $archive = new PclZip($tempfile); if (!$archive->create($physicals, PCLZIP_OPT_REMOVE_PATH, dirname($physicals[0]))) { $this->addMessage('Unable to create zip.'); if (file_exists($tempfile)) { @unlink($tempfile); } } else { Curry_Application::returnFile($tempfile, 'application/octet-stream', $name, false); @unlink($tempfile); exit; } } else { Curry_Application::returnFile($physicals[0], 'application/octet-stream', $name); } }
/** * Override the Main view. * * @return string */ public function getFinder() { if (isPost() && isset($_REQUEST['action'])) { try { // call instance method $method = 'action' . $_REQUEST['action']; if (!method_exists($this, $method)) { throw new Curry_Exception('Action does not exist.'); } $contentType = isset($_GET['iframe']) ? 'text/html' : 'application/json'; Curry_Application::returnJson($this->{$method}($_REQUEST), "", $contentType); } catch (Exception $e) { if (isAjax()) { $this->returnJson(array('status' => 0, 'error' => $e->getMessage())); } else { $this->addMessage($e->getMessage(), self::MSG_ERROR); } } } $template = Curry_Twig_Template::loadTemplateString(<<<TPL {% spaceless %} <div class="finder managedfiles"> {% if selection %} <input type="hidden" name="selection" value="{{selection}}" /> {% endif %} <div class="finder-overlay"><p></p></div> <div class="wrapper"> {% for path in paths %} <ul class="folder {{path.IsRoot?'root':''}}" data-finder='{"path":"{{path.Path}}","action":"{{path.UploadUrl}}"}'> {% for file in path.files %} <li class="{{file.IsSelected?'selected':(file.IsHighlighted?'highlighted':'')}} {{file.Icon}} {{file.IsManaged?'managedfile':''}}"><a href="{{file.Url}}" class="navigate" data-finder='{"name":"{{file.Name}}","path":"{{file.Path}}"}' title="{{file.IsManaged ? 'Managed - ' ~ attribute({'r': 'readonly', 'w':'writable'}, file.ManagedPerm) : ''}}">{{file.Name}}</a></li> {% endfor %} </ul> {% endfor %} {% if fileInfo %} <ul class="fileinfo"> {% for Key,Value in fileInfo %} <li class="fileinfo-{{Key|lower}}">{{Value|raw}}</li> {% endfor %} </ul> {% endif %} </div> <div class="btn-toolbar"> <div class="btn-group"> {% for action in actions %} <a href="{{action.Action}}" class="btn {{action.Class}}" title="{{action.Tooltip ? action.Tooltip : ''}}" data-finder='{{action.Data ? action.Data|json_encode : ''}}'>{{action.Label}}</a> {% endfor %} </div> <select></select> <div class="btn-group"> <button class="btn cancel">Cancel</button> <button class="btn btn-primary select" {{selection?'':'disabled=""'}}>Select</button> </div> </div> </div> {% endspaceless %} TPL ); $vars = array(); $selected = (array) $_GET['path']; if ($_GET['public'] == 'true') { $virtual = array(); foreach ($selected as $s) { $virtual[] = self::publicToVirtual($s); } $selected = $virtual; } // Verify selection and show selection info if (count($selected)) { try { $vars['fileInfo'] = $this->getFileInfo($selected); $selection = array(); foreach ($selected as $s) { $physical = self::virtualToPhysical($s); $public = self::virtualToPublic($s); $selection[] = $public; if (isset($_GET['type'])) { if ($_GET['type'] == 'folder' && !is_dir($physical)) { $selection = false; break; } if ($_GET['type'] == 'file' && !is_file($physical)) { $selection = false; break; } } } if ($selection) { $vars['selection'] = join(PATH_SEPARATOR, $selection); } } catch (Exception $e) { $selected = array(); } } // Show actions if ($selected && $selected[0]) { $vars['actions'] = array(array('Label' => 'Download', 'Action' => (string) url('', array('module', 'view' => 'Download', 'path' => $selected)))); if ($this->isPhysicalWritable(self::virtualToPhysical($selected[0]))) { $vars['actions'][] = array('Label' => 'Upload', 'Action' => (string) url('', array('module', 'view', 'path' => $selected[0], 'action' => 'Upload')), 'Class' => 'upload'); $vars['actions'][] = array('Label' => 'Expunge', 'Action' => (string) url('', array('module', 'view', 'path' => $selected, 'action' => 'Delete', 'method' => 'Expunge')), 'Class' => 'delete expunge', 'Tooltip' => 'Physically delete file/folder and mark Managedfile record(s) for deletion.'); $vars['actions'][] = array('Label' => 'Purge', 'Action' => (string) url('', array('module', 'view', 'path' => $selected, 'action' => 'Delete', 'method' => 'Purge')), 'Class' => 'delete purge', 'Tooltip' => 'Physically delete file/folder and Managedfile record(s).'); $vars['actions'][] = array('Label' => 'Create directory', 'Action' => (string) url('', array('module', 'view', 'path' => $selected[0], 'action' => 'CreateDirectory')), 'Class' => 'create-directory'); if (count($selected) == 1) { $vars['actions'][] = array('Label' => 'Rename', 'Action' => (string) url('', array('module', 'view', 'path' => $selected[0], 'action' => 'Rename')), 'Class' => 'rename', 'Data' => array('name' => basename($selected[0]))); } } } $vars['paths'] = self::getPaths($selected); $content = $template->render($vars); if (isAjax()) { $this->returnJson(array('content' => $content, 'maxUploadSize' => Curry_Util::computerReadableBytes(get_cfg_var('upload_max_filesize')), 'path' => $selected)); } else { return $content; } return ''; }
/** * Return partial a file to browser and exit. Will set appropriate headers and return the content. * * @deprecated Please use Curry_Application::returnPartial() instead. * * @param string $file * @param string $contentType * @param string $filename */ public function returnFile($file, $contentType, $filename) { trace_warning('DEPRECATED: ' . __CLASS__ . '::' . __METHOD__ . '(), please use Curry_Application::' . __METHOD__ . '() instead.'); Curry_Application::returnFile($file, $contentType, $filename); }
/** * Rebuild the search index. * * @param bool $ajax * @throws Exception */ public static function doRebuild($ajax = false) { $ses = new Zend_Session_Namespace(__CLASS__); $index = Curry_Core::getSearchIndex(); $app = new Curry_Application(); Curry_URL::setReverseRouteCallback(array($app, 'reverseRoute')); try { while ($ses->model < count($ses->models)) { $model = $ses->models[$ses->model]; if ($model === '@custom') { // Trigger custom indexer $ses->model++; $indexerClass = Curry_Core::$config->curry->indexerClass; if ($indexerClass && is_callable(array($indexerClass, 'build'))) { call_user_func(array($indexerClass, 'build')); } } else { // Remove old entries if (!$ses->offset) { $hits = $index->find('model:' . $model); foreach ($hits as $hit) { $index->delete($hit->id); } } $query = PropelQuery::from($model); $maxItems = $query->count(); $items = $query->offset($ses->offset)->limit($ses->limit)->find(); foreach ($items as $item) { $ses->offset++; if (!self::updateItem($item, $index, false)) { $ses->failed++; } else { $ses->success++; } } // move on to next model? if ($ses->offset >= $maxItems || count($items) < $ses->limit) { $ses->model++; $ses->offset = 0; $maxItems = 1; } } $continue = $ses->model < count($ses->models); if ($continue && $ajax) { // Return current status $part = 1 / count($ses->models); $progress = $ses->model * $part + $ses->offset / $maxItems * $part; Curry_Application::returnJson(array('progress' => round(100 * $progress), 'continue' => true, 'status' => "Indexing " . $ses->models[$ses->model] . "...")); } } // All done! if ($ajax) { $status = "Completed, " . $ses->success . ' entries updated successfully!'; if ($ses->failed) { $status .= ' ' . $ses->failed . ' items failed.'; } Curry_Application::returnJson(array('progress' => 100, 'continue' => false, 'status' => $status)); } } catch (Exception $e) { if ($ajax) { Curry_Application::returnJson(array('continue' => false, 'status' => $e->getMessage())); } else { throw $e; } } }
/** * This is partial-html used for the popup when creating or editing a user. */ public function showUser() { if (!$this->hasPermission(self::PERMISSION_USERS)) { throw new Exception('You dont have permission to access this view.'); } $user = isset($_GET['item']) ? UserQuery::create()->findPk($_GET['item']) : null; $validRoles = $this->getValidRoles(); if ($user && !array_key_exists($user->getUserRoleId(), $validRoles)) { $this->addMessage('You dont have access to users with that role.', self::MSG_ERROR); return; } // create new if user not set if (!$user) { $user = new User(); } // Validate $form = $this->getUserForm($user); $form->fillForm($user); if (isPost() && $form->isValid($_POST)) { $this->createModelUpdateEvent(get_class($user), $user->getPrimaryKey(), $user->isNew() ? 'insert' : 'update'); $this->saveUser($user, $form); if (isAjax()) { Curry_Application::returnPartial(''); } } // Render $this->addMainContent($form); }
public function dispatch(array $action, Curry_Backend $backend, array $params) { if (count($action)) { $nextAction = array_shift($action); if ($nextAction === 'json') { Curry_Application::returnJson($this->getJson($params)); } else { if ($nextAction === 'sort' && is_callable($this->options['sortable'])) { call_user_func($this->options['sortable'], $params); Curry_Application::returnJson(array('success' => 1)); } } $a = $this->actions[$nextAction]; if (!isset($a)) { throw new Exception("Action '{$nextAction}' not found."); } if (!isset($a['action'])) { throw new Exception("Action '{$nextAction}' is not defined."); } $a = $a['action']; if (is_object($a) && $a instanceof Curry_ModelView_Abstract) { $a->parentView = $this; $a->dispatch($action, $backend, $params); } else { if (is_callable($a)) { call_user_func($a, $this->getSelfSelection($params), $backend, $params, $this); } else { throw new Exception("Action '{$nextAction}' has unknown type."); } } } else { $this->render($backend, $params); } }
public function showTestEmail() { $form = $this->getTestEmailForm(); if (isPost() && $form->isValid($_POST)) { $values = $form->getValues(true); $ret = $this->sendTestEmail($values); Curry_Application::returnPartial('<pre>' . $ret . '</pre>'); } $this->addMainContent($form); }
/** {@inheritdoc} */ protected function postGeneration() { parent::postGeneration(); if ($this->inlineAdmin) { $this->adminPanel(); } else { if (Curry_Core::$config->curry->liveEdit && User::getUser()) { // Add button to toggle live edit $url = json_encode(url('', $_GET)->add(array('curry_inline_admin' => 1))->remove('curry_force_show')->getAbsolute()); $htmlHead = $this->getHtmlHead(); $htmlHead->addInlineScript(<<<JS document.addEventListener('DOMContentLoaded', function() { \tvar el = document.createElement('a'); \tel.id = 'curry-enable-live-edit'; \tel.href = {$url}; \tel.textContent = 'Live edit'; \tel.style.display = 'block'; \tel.style.position = 'fixed'; \tel.style.right = '5px'; \tel.style.top = '5px'; \tel.style.backgroundColor = 'black'; \tel.style.color = 'white'; \tel.style.padding = '5px'; \tel.style.zIndex = 1000; \tel.style.textDecoration = 'none'; \tdocument.body.appendChild(el); }); JS ); } } $appVars = Curry_Application::getInstance()->getGlobalVariables(); $appVars->HtmlHead = $this->htmlHead->getContent(); }
/** * View to execute task in seperate request. */ protected function showExecTask() { // TODO: make this a POST request $task = $_GET['task']; $defaultReturnValue = unserialize($_GET['default']); $variables = unserialize($_GET['variables']); $package = Curry_PackageManager::getPackage($_GET['package'], $_GET['version']); $returnValue = $package ? Curry_PackageManager::execTask($package, $task, $defaultReturnValue, $variables) : $defaultReturnValue; Curry_Application::returnPartial(serialize($returnValue)); }
/** * Create a mail from a URL, Page or PageRevision. * * @param string|Page|PageRevision $page * @param Curry_Request $request * @param array $variables Additional template variables. * @return Curry_Mail */ public static function createFromPage($page, $request = null, array $variables = array()) { $app = Curry_Application::getInstance(); // If a URL is provided, attempt to find page using route if (is_string($page)) { $r = new Curry_Request('GET', (string) url($page)); $page = $app->findPage($r); if (!$request) { $request = $r; } } // Find PageRevision if ($page instanceof PageRevision) { $pageRevision = $page; } elseif ($page instanceof Page) { $pageRevision = $page->getPageRevision(); if (!$pageRevision) { throw new Exception('Page has no active revision.'); } } else { throw new Exception('$page is of invalid type, expected Page or PageRevision.'); } // Create Curry_Request object if not provided $oldVal = Curry_URL::setPreventRedirect(true); if (!$request) { $url = (string) url($pageRevision->getPage()->getUrl()); $request = new Curry_Request('GET', $url); } // Generate page $pageGenerator = $app->createPageGenerator($pageRevision, $request); $content = $pageGenerator->render($variables); // Create email $mail = new Curry_Mail(); $mail->setBodyHtml($content); $mail->setBodyText(strip_tags($content)); // restore redirect status Curry_URL::setPreventRedirect($oldVal); return $mail; }