ControllerBase.php 7.89 KB
Newer Older
1
<?php
2

3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
/**
 *    Copyright (C) 2015 Deciso B.V.
 *
 *    All rights reserved.
 *
 *    Redistribution and use in source and binary forms, with or without
 *    modification, are permitted provided that the following conditions are met:
 *
 *    1. Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *
 *    THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 *    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 *    AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *    AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 *    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *    POSSIBILITY OF SUCH DAMAGE.
 *
 */
30 31
namespace OPNsense\Base;

32
use OPNsense\Core\Config;
33
use Phalcon\Mvc\Controller;
34
use Phalcon\Translate\Adapter\Gettext;
35

36 37 38 39
/**
 * Class ControllerBase implements core controller for OPNsense framework
 * @package OPNsense\Base
 */
40
class ControllerBase extends ControllerRoot
41
{
42 43
    /**
     * translate a text
Ad Schellevis's avatar
Ad Schellevis committed
44
     * @param OPNsense\Core\Config $cnf config handle
45
     * @return Gettext
46
     */
47
    public function getTranslator($cnf)
Franco Fichtner's avatar
Franco Fichtner committed
48
    {
49 50 51 52 53 54 55 56 57
        $lang = 'en_US';

        foreach ($cnf->object()->system->children() as $key => $node) {
            if ($key == 'language') {
                $lang = $node->__toString();
                break;
            }
        }

58 59 60 61 62 63 64 65 66 67 68 69
        $lang_encoding = $lang . '.UTF-8';

        $ret = new Gettext(array(
            'directory' => '/usr/local/share/locale',
            'defaultDomain' => 'OPNsense',
            'locale' => $lang_encoding,
        ));

        /* this isn't being done by Phalcon */
        putenv('LANG=' . $lang_encoding);

        return $ret;
70 71
    }

72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
    /**
     * convert xml form definition to simple data structure to use in our Volt templates
     *
     * @param $xmlNode
     * @return array
     */
    private function parseFormNode($xmlNode)
    {
        $result = array();
        foreach ($xmlNode as $key => $node) {
            switch ($key) {
                case "tab":
                    if (!array_key_exists("tabs", $result)) {
                        $result['tabs'] = array();
                    }
                    $tab = array();
                    $tab[] = $node->attributes()->id;
                    $tab[] = $node->attributes()->description;
                    if (isset($node->subtab)) {
                        $tab["subtabs"] = $this->parseFormNode($node);
                    } else {
                        $tab[] = $this->parseFormNode($node);
                    }
                    $result['tabs'][] = $tab ;
                    break;
                case "subtab":
                    $subtab = array();
                    $subtab[] = $node->attributes()->id;
                    $subtab[] = $node->attributes()->description;
                    $subtab[] = $this->parseFormNode($node);
                    $result[] = $subtab;
                    break;
                case "field":
                    // field type, containing attributes
                    $result[] = $this->parseFormNode($node);
                    break;
                case "help":
                case "hint":
                case "label":
111 112 113 114 115 116 117
                    // translate text items if gettext is enabled
                    if (function_exists("gettext")) {
                        $result[$key] = gettext((string)$node);
                    } else {
                        $result[$key] = (string)$node;
                    }

118 119 120 121 122 123 124 125 126 127 128 129
                    break;
                default:
                    // default behavior, copy in value as key/value data
                    $result[$key] = (string)$node;
                    break;
            }
        }

        return $result;
    }

    /**
130
     * parse an xml type form
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
     * @param $formname
     * @return array
     * @throws \Exception
     */
    public function getForm($formname)
    {
        $class_info = new \ReflectionClass($this);
        $filename = dirname($class_info->getFileName()) . "/forms/".$formname.".xml" ;
        if (!file_exists($filename)) {
            throw new \Exception('form xml '.$filename.' missing') ;
        }
        $formXml = simplexml_load_file($filename);
        if ($formXml === false) {
            throw new \Exception('form xml '.$filename.' not valid') ;
        }

        return $this->parseFormNode($formXml);
    }

150 151 152 153 154
    /**
     * Default action. Set the standard layout.
     */
    public function initialize()
    {
155
        // set base template
156 157
        $this->view->setTemplateBefore('default');
    }
158 159

    /**
160
     * shared functionality for all components
161
     * @param $dispatcher
162
     * @return bool
163
     * @throws \Exception
164 165 166
     */
    public function beforeExecuteRoute($dispatcher)
    {
167 168 169 170
        // only handle input validation on first request.
        if (!$dispatcher->wasForwarded()) {
            // Authentication
            // - use authentication of legacy OPNsense.
171 172
            if (!$this->doAuth()) {
                return false;
173 174
            }

175 176 177 178 179
            // check for valid csrf on post requests
            if ($this->request->isPost() && !$this->security->checkToken()) {
                // post without csrf, exit.
                return false;
            }
180

181 182 183 184 185 186 187 188 189
            // REST type calls should be implemented by inheriting ApiControllerBase.
            // because we don't check for csrf on these methods, we want to make sure these aren't used.
            if ($this->request->isHead() ||
                $this->request->isPut() ||
                $this->request->isDelete() ||
                $this->request->isPatch() ||
                $this->request->isOptions()) {
                throw new \Exception('request type not supported');
            }
190 191
        }

192 193 194 195 196
        // include csrf for volt view rendering.
        $this->view->setVars([
            'csrf_tokenKey' => $this->security->getTokenKey(),
            'csrf_token' => $this->security->getToken()
        ]);
197

198 199
        // link menu system to view, append /ui in uri because of rewrite
        $menu = new Menu\MenuSystem();
200 201 202

        // add interfaces to "Interfaces" menu tab... kind of a hack, may need some improvement.
        $cnf = Config::getInstance();
203 204 205 206

        // set translator
        $this->view->setVar('lang', $this->getTranslator($cnf));

207
        $ifarr = array();
208
        foreach ($cnf->object()->interfaces->children() as $key => $node) {
209 210 211 212 213 214 215 216 217 218
            $ifarr[$key] = $node;
        }
        ksort($ifarr);
        $ordid = 0;
        foreach ($ifarr as $key => $node) {
            $menu->appendItem('Interfaces', $key, array(
                'url' => '/interfaces.php?if='. $key,
                'order' => ($ordid++),
                'visiblename' => $node->descr ? $node->descr : strtoupper($key)
            ));
219
        }
220
        unset($ifarr);
221

222 223
        $this->view->menuSystem = $menu->getItems("/ui".$this->router->getRewriteUri());

224
        // set theme in ui_theme template var, let template handle its defaults (if there is no theme).
225 226 227
        if ($cnf->object()->theme != null && !empty($cnf->object()->theme) &&
            is_dir('/usr/local/opnsense/www/themes/'.(string)$cnf->object()->theme)
        ) {
228 229 230
            $this->view->ui_theme = $cnf->object()->theme;
        }

231 232
        // append ACL object to view
        $this->view->acl = new \OPNsense\Core\ACL();
233
    }
234
}