예제 #1
0
 /**
  * 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);
 }
예제 #2
0
 /** {@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);
         }
     }
 }
예제 #3
0
파일: List.php 프로젝트: varvanin/currycms
 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);
     }
 }
예제 #4
0
 /**
  * Return json-data to browser and exit. Will set content-type header and encode the data.
  *
  * @deprecated Use Curry_Application::returnJson() instead.
  * @param mixed $content	Data to encode with json_encode. Note that this must be utf-8 encoded. Strings will not be encoded.
  */
 public function returnJson($content)
 {
     Curry_Application::returnJson($content);
 }
예제 #5
0
    /**
     * 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">
  {% 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}}"><a href="{{file.Url}}" class="navigate" data-finder='{"name":"{{file.Name}}","path":"{{file.Path}}"}'>{{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}}" 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>
    </ul>
  </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' => 'Delete', 'Action' => (string) url('', array('module', 'view', 'path' => $selected, 'action' => 'Delete')), 'Class' => 'delete');
                $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 '';
    }
예제 #6
0
 /**
  * Get properties for tree node.
  */
 public function getTreeJson()
 {
     $packages = array();
     foreach (Curry_Propel::getModels() as $package => $classes) {
         $p = array('title' => $package, 'iconClass' => 'icon-folder-open', 'key' => $package, 'children' => array(), 'expand' => true);
         foreach ($classes as $clazz) {
             $icon = 'icon-table';
             try {
                 $count = call_user_func(array($clazz . 'Peer', 'doCount'), new Criteria());
             } catch (Exception $e) {
                 $count = '?';
                 $icon = 'icon-warning-sign';
             }
             $p['children'][] = array('title' => $clazz . ' (' . $count . ')', 'iconClass' => $icon, 'key' => $clazz, 'href' => (string) url('', array('module', 'view' => 'Table', 'table' => $clazz)));
         }
         $packages[] = $p;
     }
     Curry_Application::returnJson($packages);
 }
예제 #7
0
 /**
  * Return json-data to browser and exit. Will set content-type header and encode the data.
  * 
  * @deprecated Please use Curry_Application::returnJson() instead.
  *
  * @param mixed $content	Data to encode with json_encode. Note that this must be utf-8 encoded. Strings will not be encoded.
  */
 public function returnJson($content)
 {
     trace_warning('DEPRECATED: ' . __CLASS__ . '::' . __METHOD__ . '(), please use Curry_Application::' . __METHOD__ . '() instead.');
     Curry_Application::returnJson($content);
 }
예제 #8
0
 /**
  * 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;
         }
     }
 }
예제 #9
0
파일: Tree.php 프로젝트: varvanin/currycms
 /**
  * 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 '';
 }