public function url($p, $absolute = false, $full = false, $secure = false)
    {
        if (!is_array($p)) {
            if (strpos($p, 'http') === 0) {
                return $p;
            }

            $p = array('_action' => @func_get_arg(0));
        }

        $pre = array();
        $task = $p['_task'] ?: ($p['task'] ?: $this->task);
        $pre['_task'] = $task;
        unset($p['task'], $p['_task']);

        $url  = $this->filename;
        $delm = '?';

        foreach (array_merge($pre, $p) as $key => $val) {
            if ($val !== '' && $val !== null) {
                $par  = $key[0] == '_' ? $key : '_'.$key;
                $url .= $delm.urlencode($par).'='.urlencode($val);
                $delm = '&';
            }
        }

        $base_path = strval($_SERVER['REDIRECT_SCRIPT_URL'] ?: $_SERVER['SCRIPT_NAME']);
        $base_path = preg_replace('![^/]+$!', '', $base_path);

        if ($secure && ($token = $this->get_secure_url_token(true))) {
            // add token to the url
            $url = $token . '/' . $url;

            // remove old token from the path
            $base_path = rtrim($base_path, '/');
            $base_path = preg_replace('/\/[a-zA-Z0-9]{' . strlen($token) . '}$/', '', $base_path);

            // this need to be full url to make redirects work
            $absolute = true;
        }
        else if ($secure && ($token = $this->get_request_token()))
            $url .= $delm . '_token=' . urlencode($token);

        if ($absolute || $full) {
            // add base path to this Roundcube installation
            if ($base_path == '') $base_path = '/';
            $prefix = $base_path;

            // prepend protocol://hostname:port
            if ($full) {
                $prefix = rcube_utils::resolve_url($prefix);
            }

            $prefix = rtrim($prefix, '/') . '/';
        }
        else {
            $prefix = './';
        }

        return $prefix . $url;
    }