function Streams_before_Q_responseExtras()
{
    Q_Response::addScript('plugins/Streams/js/Streams.js');
    $host = Q_Config::get('Streams', 'node', 'host', Q_Config::get('Q', 'node', 'host', null));
    $port = Q_Config::get('Streams', 'node', 'port', Q_Config::get('Q', 'node', 'port', null));
    $user = Users::loggedInUser();
    if ($user) {
        Q_Response::setScriptData('Q.plugins.Users.loggedInUser.displayName', Streams::displayName($user));
    }
    if (!Q_Request::isAjax()) {
        $invite_url = Q_Config::get('Streams', 'invite', 'url', "http://invites.to");
        Q_Response::setScriptData('Q.plugins.Streams.invite.url', $invite_url);
        if (isset($host) && isset($port)) {
            Q_Response::setScriptData('Q.plugins.Streams.node', array("http://{$host}:{$port}"));
        }
        if ($sizes = Q_Config::expect('Streams', 'types', 'Streams/image', 'sizes')) {
            sort($sizes);
            Q_Response::setScriptData('Q.plugins.Streams.image.sizes', $sizes);
        }
        $defaults = array('readLevel' => Streams::$READ_LEVEL['messages'], 'writeLevel' => Streams::$WRITE_LEVEL['join'], 'adminLevel' => Streams::$ADMIN_LEVEL['invite']);
        Q_Response::setScriptData('Q.plugins.Streams.defaults', $defaults);
        if ($froalaKey = Q_Config::get('Streams', 'froala', 'key', null)) {
            Q_Response::setScriptData('Q.plugins.Streams.froala.key', $froalaKey);
        }
    }
    Q_Response::addStylesheet("plugins/Streams/css/Streams.css");
}
Example #2
0
function MyApp_notFound_response_content($params)
{
    header("HTTP/1.0 404 Not Found");
    $url = Q_Request::url();
    if (Q_Request::isAjax()) {
        throw new Q_Exception_NotFound(compact('url'));
    }
    return Q::view("MyApp/content/notFound.php", compact('url'));
}
Example #3
0
function Streams_participating_response()
{
    if (!Q_Request::isAjax()) {
        return;
    }
    $max_limit = Q_Config::expect('Streams', 'db', 'limits', 'participating');
    $user = Users::loggedInUser(true);
    $type = Streams::requestedType();
    $limit = Streams::requestedField('limit', false, $max_limit);
    if ($limit > $max_limit) {
        throw new Q_Exception("limit is too large, must be <= {$max_limit}");
    }
    $offset = Streams::requestedField('offset', false, 0);
    $order = Streams::requestedField('order', false, true);
    $participating = array();
    $q = Streams_Participating::select('*')->where(array('userId' => $user->id));
    if ($type) {
        $q = $q->where(array('streamName' => new Db_Range($type . '/', true, false, true)));
    }
    if ($limit) {
        $q = $q->limit($limit, $offset);
    }
    if ($order) {
        $q = $q->orderBy('updatedTime', false);
    }
    $res_participating = $q->fetchDbRows();
    foreach ($res_participating as $part) {
        $part_safe = $part->exportArray();
        if (isset($part_safe)) {
            $participating[] = $part_safe;
        }
    }
    Q_Response::setSlot('participating', $participating);
    if (!Q_Request::slotName('streams')) {
        return;
    }
    $res_streams = array();
    $streamNames = array();
    foreach ($res_participating as $p) {
        $streamNames[$p->publisherId][] = $p->streamName;
    }
    foreach ($streamNames as $p_id => $names) {
        $res_streams[$p_id] = Streams::fetch($user->id, $p_id, $names);
    }
    $streams = array();
    $o = array('asUserId' => $user->id);
    foreach ($res_streams as $publisherId => $streams_array) {
        if (!empty($streams_array)) {
            $streams[$publisherId] = array();
            foreach ($streams_array as $streamName => $stream) {
                $streams[$publisherId][$streamName] = $stream->exportArray($o);
            }
        }
    }
    Q_Response::setSlot('streams', $streams);
}
/**
 * This is the default handler for the Q/responseExtras event.
 * It should not be invoked during AJAX requests, and especially
 * not during JSONP requests. It will output things like the nonce,
 * which prevents CSRF attacks, but is only supposed to be printed
 * on our webpages and not also given to anyone who does a JSONP request.
 */
function Q_before_Q_responseExtras()
{
    $app = Q_Config::expect('Q', 'app');
    $uri = Q_Dispatcher::uri();
    $url = Q_Request::url(true);
    $base_url = Q_Request::baseUrl();
    $ajax = Q_Request::isAjax();
    if (!$uri) {
        return;
    }
    $info = array('url' => $url, 'uriString' => (string) $uri);
    if ($uri) {
        $info['uri'] = $uri->toArray();
    }
    if (!$ajax) {
        $info = array_merge(array('app' => Q_Config::expect('Q', 'app')), $info, array('proxies' => Q_Config::get('Q', 'proxies', array()), 'baseUrl' => $base_url, 'proxyBaseUrl' => Q_Uri::url($base_url), 'proxyUrl' => Q_Uri::url($url), 'sessionName' => Q_Session::name(), 'nodeUrl' => Q_Utils::nodeUrl(), 'slotNames' => Q_Config::get("Q", "response", "slotNames", array('content', 'dashboard', 'title', 'notices'))));
    }
    foreach ($info as $k => $v) {
        Q_Response::setScriptData("Q.info.{$k}", $v);
    }
    if (!$ajax) {
        $uris = Q_Config::get('Q', 'javascript', 'uris', array());
        $urls = array();
        foreach ($uris as $u) {
            $urls["{$u}"] = Q_Uri::url("{$u}");
        }
        Q_Response::setScriptData('Q.urls', $urls);
    }
    // Export more variables to inline js
    $nonce = isset($_SESSION['Q']['nonce']) ? $_SESSION['Q']['nonce'] : null;
    if ($nonce) {
        Q_Response::setScriptData('Q.nonce', $nonce);
    }
    // Attach stylesheets and scripts
    foreach (Q_Config::get('Q', 'javascript', 'responseExtras', array()) as $src => $b) {
        if (!$b) {
            continue;
        }
        Q_Response::addScript($src);
    }
    foreach (Q_Config::get('Q', 'stylesheets', 'responseExtras', array()) as $src => $media) {
        if (!$media) {
            continue;
        }
        if ($media === true) {
            $media = 'screen,print';
        }
        Q_Response::addStylesheet($src, null, $media);
    }
}
function Users_before_Q_responseExtras()
{
    Q_Response::addScript('plugins/Users/js/Users.js');
    $app = Q_Config::expect('Q', 'app');
    $requireLogin = Q_Config::get('Users', 'requireLogin', array());
    $rl_array = array();
    foreach ($requireLogin as $rl => $value) {
        $rl_array[Q_Uri::url($rl)] = $value;
    }
    if (!Q_Request::isAjax()) {
        Q_Response::setScriptData('Q.plugins.Users.requireLogin', $rl_array);
        $successUrl = Q_Config::get('Users', 'uris', "{$app}/successUrl", "{$app}/home");
        $afterActivate = Q_Config::get('Users', 'uris', "{$app}/afterActivate", $successUrl);
        $loginOptions = Q_Config::get('Users', 'login', array("identifierType" => 'email,mobile', "userQueryUri" => 'Users/user', "using" => "native,facebook", "noRegister" => false));
        $loginOptions["afterActivate"] = Q_Uri::url($afterActivate);
        $loginOptions["successUrl"] = Q_Uri::url($successUrl);
        Q_Response::setScriptData('Q.plugins.Users.login.serverOptions', $loginOptions);
        $setIdentifierOptions = Q::take($loginOptions, array('identifierType'));
        Q_Response::setScriptData('Q.plugins.Users.setIdentifier.serverOptions', $setIdentifierOptions);
    }
    $fb_app_info = Q_Config::get('Users', 'facebookApps', $app, array());
    if ($fb_app_info) {
        unset($fb_app_info['secret']);
        Q_Response::setScriptData("Q.plugins.Users.facebookApps.{$app}", $fb_app_info);
    }
    if ($node_server_url = Q_Config::get('Users', 'nodeServer', 'url', null)) {
        Q_Response::setScriptData("Q.plugins.Users.nodeServer", parse_url($node_server_url));
    }
    if (Q_Config::get('Users', 'showLoggedInUser', true)) {
        $user = Q_Session::id() ? Users::loggedInUser() : null;
        if ($user) {
            $u = $user->exportArray();
            $u['sessionCount'] = $user->sessionCount;
            Q_Response::setScriptData("Q.plugins.Users.loggedInUser", $u);
            Q_Response::addScriptLine("Q.plugins.Users.loggedInUser = new Q.plugins.Users.User(Q.plugins.Users.loggedInUser);");
        }
    }
    Q_Response::setScriptData('Q.plugins.Users.communityId', Users::communityId());
    Q_Response::setScriptData('Q.plugins.Users.communityName', Users::communityName());
    Q_Response::setScriptData('Q.plugins.Users.communitySuffix', Users::communitySuffix());
    Q_Response::setScriptData('Q.plugins.Users.hinted', Q::ifset($_SESSION, 'Users', 'hinted', array()));
    if ($sizes = Q_Config::expect('Users', 'icon', 'sizes')) {
        sort($sizes);
        Q_Response::setScriptData('Q.plugins.Users.icon.sizes', $sizes);
    }
    $defaultSize = Q_Config::get('Users', 'icon', 'defaultSize', 40);
    Q_Response::setScriptData('Q.plugins.Users.icon.defaultSize', $defaultSize);
    Q_Response::addStylesheet("plugins/Users/css/Users.css");
}
Example #6
0
function Q_after_Q_tool_render($params, &$result)
{
    $info = $params['info'];
    $extra = $params['extra'];
    if (!is_array($extra)) {
        $extra = array();
    }
    $id_prefix = Q_Html::getIdPrefix();
    $tool_ids = Q_Html::getToolIds();
    $tag = Q::ifset($extra, 'tag', 'div');
    if (empty($tag)) {
        Q_Html::popIdPrefix();
        return;
    }
    $classes = '';
    $data_options = '';
    $count = count($info);
    foreach ($info as $name => $opt) {
        $classes = ($classes ? "{$classes} " : $classes) . implode('_', explode('/', $name)) . '_tool';
        $options = Q_Response::getToolOptions($name);
        if (isset($options)) {
            $friendly_options = str_replace(array('&quot;', '\\/'), array('"', '/'), Q_Html::text(Q::json_encode($options)));
        } else {
            $friendly_options = '';
        }
        $normalized = Q_Utils::normalize($name, '-');
        if (isset($options) or $count > 1) {
            $id = $tool_ids[$name];
            $id_string = $count > 1 ? "{$id} " : '';
            $data_options .= " data-{$normalized}='{$id_string}{$friendly_options}'";
        }
        $names[] = $name;
    }
    if (isset($extra['classes'])) {
        $classes .= ' ' . $extra['classes'];
    }
    $attributes = isset($extra['attributes']) ? ' ' . Q_Html::attributes($extra['attributes']) : '';
    $data_retain = !empty($extra['retain']) || Q_Response::shouldRetainTool($id_prefix) ? " data-Q-retain=''" : '';
    $data_replace = !empty($extra['replace']) || Q_Response::shouldReplaceWithTool($id_prefix) ? " data-Q-replace=''" : '';
    $names = $count === 1 ? ' ' . key($info) : 's ' . implode(" ", $names);
    $ajax = Q_Request::isAjax();
    $result = "<{$tag} id='{$id_prefix}tool' " . "class='Q_tool {$classes}'{$data_options}{$data_retain}{$data_replace}{$attributes}>" . "{$result}</{$tag}>";
    if (!Q_Request::isAjax()) {
        $result = "<!--\nbegin tool{$names}\n-->{$result}<!--\nend tool{$names} \n-->";
    }
    Q_Html::popIdPrefix();
}
Example #7
0
function Q_exception_native($params)
{
    extract($params);
    /**
     * @var Exception $exception 
     */
    if ($is_ajax = Q_Request::isAjax()) {
        $json = @Q::json_encode(array('errors' => Q_Exception::toArray(array($exception))));
        $callback = Q_Request::callback();
        switch (strtolower($is_ajax)) {
            case 'iframe':
                // Render an HTML layout for ajax
                if (!Q_Response::$batch) {
                    header("Content-type: text/html");
                }
                echo <<<EOT
<!doctype html><html lang=en>
<head><meta charset=utf-8><title>Q Result</title></head>
<body>
<script type="text/javascript">
window.result = function () { return {$json} };
</script>
</body>
</html>
EOT;
                break;
            case 'json':
                // Render a JSON layout for ajax
            // Render a JSON layout for ajax
            default:
                header("Content-type: " . ($callback ? "application/javascript" : "application/json"));
                echo $callback ? "{$callback}({$json})" : $json;
        }
    } else {
        if (Q::textMode()) {
            echo Q_Exception::coloredString($exception);
            exit;
        }
        $message = $exception->getMessage();
        $file = $exception->getFile();
        $line = $exception->getLine();
        if (is_callable(array($exception, 'getTraceAsStringEx'))) {
            $trace_string = $exception->getTraceAsStringEx();
        } else {
            $trace_string = $exception->getTraceAsString();
        }
        if ($exception instanceof Q_Exception_PhpError or !empty($exception->messageIsHtml)) {
            // do not sanitize $message
        } else {
            $message = Q_Html::text($message);
        }
        $content = "<h1 class='exception_message'>{$message}</h1>";
        if (Q_Config::get('Q', 'exception', 'showFileAndLine', true)) {
            $content .= "<h3 class='exception_fileAndLine'>in {$file} ({$line})</h3>";
        }
        if (Q_Config::get('Q', 'exception', 'showTrace', true)) {
            $content .= "<pre class='exception_trace'>{$trace_string}</pre>";
        }
        $content .= str_repeat(' ', 512);
        // because of chrome
        $title = "Exception occurred";
        $dashboard = "";
        echo Q::view('Q/layout/html.php', compact('content', 'dashboard', 'title'));
    }
    $app = Q_Config::get('Q', 'app', null);
    $colored = Q_Exception::coloredString($exception);
    Q::log("{$app}: Exception in " . ceil(Q::milliseconds()) . "ms:\n\n{$colored}\n", null, true, array('maxLength' => 10000));
}
Example #8
0
 /**
  * @method writeHandler
  * @static
  * @param {string} $id
  * @param {string} $sess_data
  * @return {boolean}
  */
 static function writeHandler($id, $sess_data)
 {
     try {
         // if the request is AJAX request that came without session cookie, then do not write session, ignore it
         if (Q_Request::isAjax() && !isset($_COOKIE[self::name()])) {
             return false;
         }
         // don't save sessions when running from command-line (cli)
         if (php_sapi_name() == 'cli') {
             return false;
         }
         /**
          * @event Q/session/write {before}
          * @param {string} id
          * @param {string} sess_data
          * @return {boolean}
          */
         if (false === Q::event('Q/session/write', compact('id', 'sess_data'), 'before')) {
             return false;
         }
         if (empty(self::$session_save_path)) {
             self::$session_save_path = self::savePath();
         }
         if (!empty(self::$session_db_connection)) {
             // Create a new row to be saved in the session table
             $db_row_class = self::$session_db_row_class;
             // Make sure it has a primary key!
             if (count(self::$session_db_row->getPrimaryKey()) != 1) {
                 throw new Q_Exception("The primary key of " . self::$session_db_row_class . " has to consist of exactly 1 field!");
             }
             $id_field = self::$session_db_id_field;
             $data_field = self::$session_db_data_field;
             $updated_field = self::$session_db_updated_field;
             $duration_field = self::$session_db_duration_field;
             $row = self::$session_db_row;
             if (!$row->wasRetrieved()) {
                 $row->{$id_field} = $id;
             }
             $row->{$data_field} = $sess_data;
             $row->{$duration_field} = Q_Config::get('Q', 'session', 'durations', Q_Request::formFactor(), Q_Config::expect('Q', 'session', 'durations', 'session'));
             /**
              * @event Q/session/save {before}
              * @param {string} id
              * @param {string} sess_data
              * @return {boolean}
              */
             if (false === Q::event('Q/session/save', array('row' => $row, 'id_field' => $id_field, 'data_field' => $data_field, 'updated_field' => $updated_field, 'duration_field' => $duration_field), 'before')) {
                 return false;
             }
             $row->save(false, true);
             $result = true;
         } else {
             $duration_name = self::durationName();
             $id1 = substr($id, 0, 4);
             $id2 = substr($id, 4);
             $ssp = self::$session_save_path;
             $sess_file = $ssp . DS . "{$duration_name}/{$id1}/{$id2}";
             $dir = $ssp . DS . "{$duration_name}/{$id1}/";
             if (!is_dir($dir)) {
                 mkdir($dir, fileperms($ssp), true);
             }
             if (!is_writable($dir)) {
                 // alert the developer to this problem
                 Q::log("{$sess_file} is not writable", 'fatal');
                 die("{$sess_file} is not writable");
             }
             $fp = fopen($sess_file, "w");
             if (!$fp) {
                 return false;
             }
             $result = fwrite($fp, $sess_data);
             fclose($fp);
         }
         $changed = $sess_data !== self::$sess_data;
         $old_data = self::$sess_data;
         /**
          * @event Q/session/write {after}
          * @param {string} id
          * @param {string} sess_data
          * @param {string} data_field
          * @param {string} updated_field
          * @param {string} duration_field
          * @param {string} sess_file
          * @param {integer} row
          * @param {boolean} changed
          * @param {string} old_data
          * @return {mixed}
          */
         $result = Q::event('Q/session/write', compact('id', 'sess_data', 'data_field', 'updated_field', 'duration_field', 'sess_file', 'row', 'changed', 'old_data'), 'after');
         return $result;
     } catch (Exception $e) {
         Q::log("Exception when writing session {$id}: " . $e->getMessage());
         throw $e;
     }
 }
Example #9
0
 /**
  * Sets a header to redirect to a given URI or URL.
  * @method redirect
  * @static
  * @param {string} $uri The URL or internal URI to redirect to
  * @param {array} $options An array of options that can include:
  *  "loop" => Defaults to false. If true, sets the redirect header even if the current URL is the same.
  *  "noProxy" => Defaults to false. If true, doesn't use the proxy mapping to determine URL
  *  "permanently" => If true, sets response code as 304 instead of 302
  * @param {boolean} [$noProxy=false]
  * @return {boolean}
  *  Return whether the redirect header was set.
  */
 static function redirect($uri, $options = array())
 {
     extract($options);
     $url = Q_Uri::url($uri, null, !empty($noProxy));
     if ($url === Q_Uri::unreachableUri()) {
         throw new Q_Exception_BadValue(array('internal' => 'uri', 'problem' => 'no url routes to it'));
     }
     $level = ob_get_level();
     for ($i = 0; $i < $level; ++$i) {
         ob_clean();
     }
     /**
      * @event Q/response {before}
      * @param {string} permanently
      * @param {string} uri
      * @param {string} url
      * @param {string} loop
      * @return {boolean}
      */
     $result = Q::event('Q/redirect', compact('uri', 'url', 'loop', 'permanently', 'noProxy', 'level'), 'before');
     if (isset($result)) {
         return $result;
     }
     if (!empty($loop) and Q_Request::url() === $url) {
         return false;
     }
     if (!Q_Request::isAjax()) {
         if (!empty($permanently)) {
             header("HTTP/1.1 301 Moved Permanently");
         }
         header("Location: {$url}");
     }
     self::$redirected = $uri;
     return true;
 }
Example #10
0
/**
 * The default implementation.
 */
function Q_errors($params)
{
    extract($params);
    /**
     * @var Exception $exception
     * @var boolean $startedResponse
     */
    if (!empty($exception)) {
        Q_Response::addError($exception);
    }
    $errors = Q_Response::getErrors();
    $errors_array = Q_Exception::toArray($errors);
    // Simply return the errors, if this was an AJAX request
    if ($is_ajax = Q_Request::isAjax()) {
        try {
            $errors_json = @Q::json_encode($errors_array);
        } catch (Exception $e) {
            $errors_array = array_slice($errors_array, 0, 1);
            unset($errors_array[0]['trace']);
            $errors_json = @Q::json_encode($errors_array);
        }
        $json = "{\"errors\": {$errors_json}}";
        $callback = Q_Request::callback();
        switch (strtolower($is_ajax)) {
            case 'iframe':
                if (!Q_Response::$batch) {
                    header("Content-type: text/html");
                }
                echo <<<EOT
<!doctype html><html lang=en>
<head><meta charset=utf-8><title>Q Result</title></head>
<body>
<script type="text/javascript">
window.result = function () { return {$json} };
</script>
</body>
</html>
EOT;
                break;
            case 'json':
            default:
                header("Content-type: " . ($callback ? "application/javascript" : "application/json"));
                echo $callback ? "{$callback}({$json})" : $json;
        }
        return;
    }
    // Forward internally, if it was requested
    if ($onErrors = Q_Request::special('onErrors', null)) {
        $uri1 = Q_Dispatcher::uri();
        $uri2 = Q_Uri::from($onErrors);
        $url2 = $uri2->toUrl();
        if (!isset($uri2)) {
            throw new Q_Exception_WrongValue(array('field' => 'onErrors', 'range' => 'an internal URI reachable from a URL'));
        }
        if ($uri1->toUrl() !== $url2) {
            Q_Dispatcher::forward($uri2);
            return;
            // we don't really need this, but it's here anyway
        }
    }
    $params2 = compact('errors', 'exception', 'errors_array', 'exception_array');
    if (Q::eventStack('Q/response')) {
        // Errors happened while rendering response. Just render errors view.
        return Q::view('Q/errors.php', $params2);
    }
    if (!$startedResponse) {
        try {
            // Try rendering the response, expecting it to
            // display the errors along with the rest.
            $ob = new Q_OutputBuffer();
            Q::event('Q/response', $params2);
            $ob->endFlush();
            return;
        } catch (Exception $e) {
            if (get_class($e) === 'Q_Exception_DispatcherForward') {
                throw $e;
                // if forwarding was requested, do it
                // for all other errors, continue trying other things
            }
            $output = $ob->getClean();
        }
    }
    if ($errors) {
        // Try rendering the app's errors response, if any.
        $app = Q::app();
        if (Q::canHandle("{$app}/errors/response/content")) {
            Q_Dispatcher::forward("{$app}/errors");
        } else {
            echo Q::view("Q/errors.php", compact('errors'));
        }
    }
    if (!empty($e)) {
        return Q::event('Q/exception', array('exception' => $e));
    }
}
Example #11
0
/**
 * Default Q/response handler.
 * 1. Gets some slots, depending on what was requested.
 * 2. Renders them in a layout
 *    The layout expects "title", "dashboard" and "contents" slots to be filled.
 */
function Q_response($params)
{
    extract($params);
    /**
     * @var Exception $exception
     * @var array $errors
     */
    if (empty($errors)) {
        $errors = Q_Response::getErrors();
    }
    if (!empty($_GET['Q_ct'])) {
        Q_Response::setCookie('Q_ct', $_GET['Q_ct']);
    }
    // If output is set, use that
    $output = Q_Response::output();
    if (isset($output)) {
        if ($output === true) {
            return;
        }
        if (is_string($output)) {
            echo $output;
        }
        return;
    }
    // Redirect to success page, if requested.
    $isAjax = Q_Request::isAjax();
    if (empty($errors) and empty($exception)) {
        if (!$isAjax and null !== Q_Request::special('onSuccess', null)) {
            $onSuccess = Q_Request::special('onSuccess', null);
            if (Q_Config::get('Q', 'response', 'onSuccessShowFrom', true)) {
                $onSuccess = Q_Uri::url($onSuccess . '?Q.fromSuccess=' . Q_Dispatcher::uri());
            }
            Q_Response::redirect($onSuccess);
            return;
        }
    }
    // Get the requested module
    $uri = Q_Dispatcher::uri();
    if (!isset($module)) {
        $module = $uri->module;
        if (!isset($module)) {
            $module = 'Q';
            Q_Dispatcher::uri()->module = 'Q';
        }
    }
    if (!$isAjax || Q_Request::isLoadExtras()) {
        Q::event('Q/responseExtras', array(), 'before');
    }
    // Get the main module (the app)
    $app = Q_Config::expect('Q', 'app');
    $action = $uri->action;
    if (Q::canHandle("{$module}/{$action}/response")) {
        if (false === Q::event("{$module}/{$action}/response") and !$isAjax) {
            return;
        }
    }
    $slotNames = Q_Request::slotNames(true);
    $idPrefixes = array();
    if ($temp = Q_Request::special('idPrefixes', null)) {
        foreach (explode(',', $temp) as $i => $prefix) {
            if (!isset($slotNames[$i])) {
                throw new Q_Exception("More id prefixes than slot names", "Q.idPrefixes");
            }
            $idPrefixes[$slotNames[$i]] = $prefix;
        }
    }
    // What to do if this is an AJAX request
    if ($isAjax) {
        $to_encode = array();
        if (Q_Response::$redirected) {
            // We already called Q_Response::redirect
            $to_encode['redirect']['url'] = Q_Uri::url(Q_Response::$redirected);
            try {
                $to_encode['redirect']['uri'] = Q_Uri::from(Q_Response::$redirected)->toArray();
            } catch (Exception $e) {
                // couldn't get internal URI
            }
        } else {
            if (is_array($slotNames)) {
                foreach ($slotNames as $slotName) {
                    Q_Response::fillSlot($slotName, 'default', Q::ifset($idPrefixes, $slotName, null));
                }
                // Go through the slots again, because other handlers may have overwritten
                // their contents using Q_Response::setSlot()
                foreach ($slotNames as $sn) {
                    Q_Response::fillSlot($sn, 'default', Q::ifset($idPrefixes, $slotName, null));
                }
                if (Q_Response::$redirected) {
                    // While rendering the slots we called Q_Redirect
                    $to_encode['redirect']['url'] = Q_Uri::url(Q_Response::$redirected);
                    try {
                        $to_encode['redirect']['uri'] = Q_Uri::from(Q_Response::$redirected)->toArray();
                    } catch (Exception $e) {
                        // couldn't get internal URI
                    }
                } else {
                    if (Q_Request::isLoadExtras()) {
                        $to_encode['slots'] = Q_Response::slots(true);
                        // add stylesheets, stylesinline, scripts, scriptlines, scriptdata, templates
                        foreach (array_merge(array(''), $slotNames) as $slotName) {
                            $temp = Q_Response::stylesheetsArray($slotName);
                            if ($temp) {
                                $to_encode['stylesheets'][$slotName] = $temp;
                            }
                            $temp = Q_Response::stylesInline($slotName);
                            if ($temp) {
                                $to_encode['stylesInline'][$slotName] = $temp;
                            }
                            $temp = Q_Response::scriptsArray($slotName);
                            if ($temp) {
                                $to_encode['scripts'][$slotName] = $temp;
                            }
                            $temp = Q_Response::scriptLines($slotName, true, "\n", false);
                            if ($temp) {
                                $to_encode['scriptLines'][$slotName] = $temp;
                            }
                            $temp = Q_Response::scriptData($slotName);
                            if ($temp) {
                                $to_encode['scriptData'][$slotName] = $temp;
                            }
                            $temp = Q_Response::templateData($slotName);
                            if ($temp) {
                                $to_encode['templates'][$slotName] = $temp;
                            }
                        }
                    } else {
                        $to_encode['slots'] = Q_Response::slots(true);
                        // add stylesinline, scriptlines, scriptdata, templates
                        foreach (array_merge(array(''), $slotNames) as $slotName) {
                            $temp = Q_Response::stylesInline($slotName);
                            if ($temp) {
                                $to_encode['stylesInline'][$slotName] = $temp;
                            }
                            $temp = Q_Response::scriptData($slotName);
                            if ($temp) {
                                $to_encode['scriptData'][$slotName] = $temp;
                            }
                            $temp = Q_Response::scriptLines($slotName, true, "\n", false);
                            if ($temp) {
                                $to_encode['scriptLines'][$slotName] = $temp;
                            }
                        }
                    }
                }
            }
        }
        $to_encode['timestamp'] = microtime(true);
        $echo = Q_Request::contentToEcho();
        if (isset($echo)) {
            $to_encode['echo'] = $echo;
        }
        $json = Q::json_encode(Q::cutoff($to_encode));
        $callback = Q_Request::callback();
        switch (strtolower($isAjax)) {
            case 'iframe':
                if (!Q_Response::$batch) {
                    header("Content-type: text/html");
                }
                echo <<<EOT
<!doctype html><html lang=en>
<head><meta charset=utf-8><title>Q Result</title></head>
<body>
<script type="text/javascript">
window.result = function () { return {$json} };
</script>
</body>
</html>
EOT;
                break;
            case 'json':
            default:
                if (!Q_Response::$batch) {
                    header("Content-type: " . ($callback ? "application/javascript" : "application/json"));
                }
                echo $callback ? "{$callback}({$json})" : $json;
        }
        return;
    }
    // If this is a request for a regular webpage,
    // fill the usual slots and render a layout.
    if (Q_Response::$redirected) {
        return;
        // If already set a redirect header, simply return -- no reason to output all this HTML
    }
    static $added_Q_init = false;
    if (!$added_Q_init) {
        Q_Response::addScriptLine("\n// Now, initialize Q\nQ.init();\n", null, 'Q');
        $added_Q_init = true;
    }
    // Get all the usual slots for a webpage
    $slots = array();
    foreach ($slotNames as $sn) {
        Q_Response::fillSlot($sn, 'default', Q::ifset($idPrefixes, $sn, null));
    }
    // Go through the slots again, because other handlers may have overwritten
    // their contents using Q_Response::setSlot()
    foreach ($slotNames as $sn) {
        Q_Response::fillSlot($sn, 'default', Q::ifset($idPrefixes, $sn, null));
    }
    $output = Q_Response::output();
    if (isset($output)) {
        if ($output === true) {
            return;
        }
        if (is_string($output)) {
            echo $output;
        }
        return;
    }
    if (!$isAjax or Q_Request::isLoadExtras()) {
        Q::event('Q/responseExtras', array(), 'after');
    }
    $slots = Q_Response::slots(false);
    // Render a full HTML layout
    $layout_view = Q_Response::layoutView();
    echo Q::view($layout_view, $slots);
}
Example #12
0
 /**
  * @method writeHandler
  * @static
  * @param {string} $id
  * @param {string} $sess_data
  * @return {boolean}
  */
 static function writeHandler($id, $sess_data)
 {
     try {
         // if the request is AJAX request that came without session cookie, then do not write session, ignore it
         if (Q_Request::isAjax() && !isset($_COOKIE[self::name()])) {
             return false;
         }
         // don't save sessions when running from command-line (cli)
         if (php_sapi_name() == 'cli') {
             return false;
         }
         $our_SESSION = $_SESSION;
         $old_data = self::$sess_data;
         $changed = $sess_data !== $old_data;
         $result = false;
         /**
          * @event Q/session/write {before}
          * @param {string} id
          * @param {string} sess_data
          * @param {string} old_data
          * @param {boolean} changed
          * @return {boolean}
          */
         if (false === Q::event('Q/session/write', compact('id', 'sess_data', 'old_data', 'changed'), 'before')) {
             return false;
         }
         if (empty(self::$session_save_path)) {
             self::$session_save_path = self::savePath();
         }
         if (!empty(self::$session_db_connection)) {
             // Create a new row to be saved in the session table
             $db_row_class = self::$session_db_row_class;
             // Make sure it has a primary key!
             if (count(self::$session_db_row->getPrimaryKey()) != 1) {
                 throw new Q_Exception("The primary key of " . self::$session_db_row_class . " has to consist of exactly 1 field!");
             }
             $id_field = self::$session_db_id_field;
             $data_field = self::$session_db_data_field;
             $updated_field = self::$session_db_updated_field;
             $duration_field = self::$session_db_duration_field;
             $row = self::$session_db_row;
             $row->{$id_field} = $id;
         } else {
             $duration_name = self::durationName();
             $id1 = substr($id, 0, 4);
             $id2 = substr($id, 4);
             $ssp = self::$session_save_path;
             $sess_file = $ssp . DS . "{$duration_name}/{$id1}/{$id2}";
             $dir = $ssp . DS . "{$duration_name}/{$id1}/";
         }
         if ($changed) {
             // Apparently, we want to save some changes.
             // The convention to avoid locking is that everything
             // stored in sessions must be mergeable using the
             // Q_Tree merge algorithm.
             // So we will retrieve the latest session data again,
             // merge our changes over it, and save.
             $params = array('id_field' => $id_field, 'data_field' => $data_field, 'updated_field' => $updated_field, 'duration_field' => $duration_field, 'changed' => $changed, 'sess_data' => $sess_data, 'old_data' => $old_data);
             if (!empty(self::$session_db_connection)) {
                 $row->retrieve();
                 $existing_data = Q::ifset($row, $data_field, "");
                 $params['row'] = $row;
             } else {
                 if (!is_dir($dir)) {
                     mkdir($dir, fileperms($ssp), true);
                 }
                 if (!is_writable($dir)) {
                     // alert the developer to this problem
                     Q::log("{$sess_file} is not writable", 'fatal');
                     die("{$sess_file} is not writable");
                 }
                 $file = fopen($sess_file, "w");
                 if (!$file) {
                     return false;
                 }
                 $params['row'] = $row;
                 $maxlength = Q_Config::get('Q', 'session', 'maxlength', 4095);
                 $existing_data = fread($file, $maxlength);
             }
             $_SESSION = session_decode($existing_data);
             if (!$_SESSION) {
                 $_SESSION = array();
             }
             $t = new Q_Tree($_SESSION);
             $t->merge($our_SESSION);
             $_SESSION = $t->getAll();
             $params['existing_data'] = $existing_data;
             $params['merged_data'] = $merged_data = session_encode();
             /**
              * @event Q/session/save {before}
              * @param {string} sess_data
              * @param {string} old_data
              * @param {string} existing_data
              * @param {string} merged_data
              * @param {boolean} changed
              * @param {Db_Row} row
              * @return {boolean}
              */
             if (false === Q::event('Q/session/save', $params, 'before')) {
                 return false;
             }
             if (!empty(self::$session_db_connection)) {
                 $row->{$data_field} = $merged_data;
                 $row->{$duration_field} = Q_Config::get('Q', 'session', 'durations', Q_Request::formFactor(), Q_Config::expect('Q', 'session', 'durations', 'session'));
                 $row->save();
                 $result = true;
             } else {
                 $result = fwrite($file, $merged_data);
                 fclose($file);
             }
         }
         /**
          * @event Q/session/write {after}
          * @param {string} id
          * @param {boolean} changed
          * @param {string} sess_data
          * @param {string} old_data
          * @param {string} existing_data
          * @param {string} merged_data
          * @param {string} data_field
          * @param {string} updated_field
          * @param {string} duration_field
          * @param {string} sess_file
          * @param {integer} row
          * @return {mixed}
          */
         $result = Q::event('Q/session/write', compact('id', 'data_field', 'updated_field', 'duration_field', 'sess_file', 'row', 'changed', 'sess_data', 'old_data', 'existing_data', 'merged_data'), 'after');
         return $result;
     } catch (Exception $e) {
         Q::log("Exception when writing session {$id}: " . $e->getMessage());
         throw $e;
     }
 }