function users_after_pie_reroute($params, &$stop_dispatch) { $uri = Pie_Dispatcher::uri(); $app = Pie_Config::expect('pie', 'app'); $ma = $uri->module . '/' . $uri->action; $requireComplete = Pie_Config::get('users', 'requireComplete', array()); if (isset($requireComplete[$ma])) { $redirect_action = is_string($requireComplete[$ma]) ? $requireComplete[$ma] : "{$app}/login"; $test_complete = true; } else { $requireLogin = Pie_Config::get('users', 'requireLogin', array()); if (!isset($requireLogin[$ma])) { // We don't have to require complete or login here return; } $redirect_action = is_string($requireLogin[$ma]) ? $requireLogin[$ma] : "{$app}/login"; } // First, try to get the user $user = Users::loggedInUser(); if (!$user) { // Try authenticating with facebook $module = Pie_Dispatcher::uri()->module; $app_id = Pie_Config::expect('users', 'facebookApps', $module, 'appId'); $user = Users::authenticate('facebook', $app_id); } if (!$user) { $uri->onSuccess = $uri->module . '/' . $uri->action; $uri->onCancel = "{$app}/welcome"; if ($uri->onSuccess === $redirect_action) { // avoid a redirect loop $uri->onSuccess = "{$app}/home"; } $parts = explode('/', $redirect_action); $uri->action = $parts[0]; $uri->action = $parts[1]; } // If have requireLogin but not requireComplete, then // simply change the underlying URI without redirecting if (empty($test_complete)) { return; } // If we are here, we should check if the user account is complete $complete = Pie::event('users/account/complete'); if ($complete) { // good, nothing else to complete return; } // redirect to account page $account_action = Pie_Config::expect('users', 'accountAction', $uri->module); if ($ma != $account_action) { // Make the user launch into setting up their account. // If they want to return to this URL later, they can do it on their own. Pie_Response::redirect($account_action); $stop_dispatch = true; return; } }
function users_before_pie_init() { $facebook_apps = Pie_Config::get('users', 'facebookApps', array()); foreach ($facebook_apps as $app_id => $fb_info) { if (isset($fb_info['url'])) { $subpath = isset($fb_info['subpath']) ? $fb_info['subpath'] : ''; Pie_Config::set('pie', 'proxies', Pie_Request::baseUrl(true) . $subpath, $fb_info['url']); } } }
function pie_response_title() { // The default title $title = Pie_Config::get('pie', 'app', basename(APP_DIR)); $action = Pie_Dispatcher::uri()->action; if ($action) { $title .= ": {$action}"; } return $title; }
function users_after_pie_addScriptLines() { $app = Pie_Config::expect('pie', 'app'); $app_json = json_encode($app); $fb_app_info = Pie_Config::get('users', 'facebookApps', $app, array()); if ($fb_app_info) { unset($fb_app_info['secret']); $fb_app_info_json = json_encode($fb_app_info); Pie_Response::addScriptLine("// users {{ \n" . "\t\tif (!Pie) Pie = {}; if (!Pie.Users) Pie.Users = {};\n" . "\t\tif (!Pie.Users.facebookApps) Pie.Users.facebookApps = {};\n" . "\t\tPie.Users.facebookApps[{$app_json}] = {$fb_app_info_json}\n" . "// }} users \n"); } }
static function execute() { // Fixes for different platforms: if (isset($_SERVER['HTTP_X_REWRITE_URL'])) { // ISAPI 3.0 $_SERVER['REQUEST_URI'] = $_SERVER['HTTP_X_REWRITE_URL']; } // Define a constant if (!defined('PIE_CONTROLLER')) { define('PIE_CONTROLLER', 'Pie_ActionController'); } try { $parts = explode('/', Pie_Request::tail()); $parts_len = count($parts); if ($parts_len >= 1) { $module = $parts[0]; } if ($parts_len >= 2) { $action = $parts[1]; } // Make sure the 'pie'/'web' config fields are set, // otherwise URLs will be formed pointing to the wrong // controller script. $ar = Pie_Config::get('pie', 'web', 'appRootUrl', null); if (!isset($ar)) { throw new Pie_Exception_MissingConfig(array('fieldpath' => 'pie/web/appRootUrl')); } $cs = Pie_Config::get('pie', 'web', 'controllerSuffix', null); if (!isset($cs)) { throw new Pie_Exception_MissingConfig(array('fieldpath' => 'pie/web/controllerSuffix')); } // Dispatch the request $uri = Pie_Uri::from(compact('module', 'action')); Pie_Dispatcher::dispatch($uri); $dispatch_result = Pie_Dispatcher::result(); if (!isset($dispatch_result)) { $dispatch_result = 'Ran dispatcher'; } $uri = Pie_Dispatcher::uri(); $module = $uri->module; $action = $uri->action; if ($module and $action) { $slot_names = Pie_Request::slotNames(); $requested_slots = empty($slot_names) ? '' : implode(',', array_keys($slot_names)); Pie::log("~" . ceil(Pie::microtime()) . 'ms+' . ceil(memory_get_peak_usage() / 1000) . 'kb.' . " {$dispatch_result} for {$module}/{$action}" . " ({$requested_slots})"); } else { Pie::log("~" . ceil(Pie::microtime()) . 'ms+' . ceil(memory_get_peak_usage() / 1000) . 'kb.' . " No route for " . $_SERVER['REQUEST_URI']); } } catch (Exception $exception) { Pie::event('pie/exception', compact('exception')); } }
function users_register_post_download($url, $folder, $size = 80) { $url_parts = parse_url($url); if (substr($url_parts['host'], -12) != 'gravatar.com') { return false; } $dir = Pie_Config::get('users', 'paths', 'icons', 'files/users/icons'); $ch = curl_init(Pie_Uri::url($_REQUEST['icon'] . '?s=' . $size)); $dir2 = Pie::realPath($dir) . DS . $folder; if (!file_exists($dir2)) { mkdir($dir2, 0777); chmod($dir2, 0777); } $fp = fopen($dir2 . DS . "{$size}.png", 'wb'); curl_setopt($ch, CURLOPT_FILE, $fp); curl_setopt($ch, CURLOPT_HEADER, 0); curl_exec($ch); curl_close($ch); fclose($fp); return true; }
function pie_exception($params) { extract($params); /** * @var Exception $exception */ $message = $exception->getMessage(); $file = $exception->getFile(); $line = $exception->getLine(); if ($is_ajax = Pie_Request::isAjax()) { // Render a JSON layout for ajax switch (strtolower($is_ajax)) { case 'json': default: $json = json_encode(array('errors' => Pie_Exception::toArray(array($exception)))); $callback = Pie_Request::callback(); echo "{$callback}({$json})"; } } else { if (is_callable(array($exception, 'getTraceAsStringEx'))) { $trace_string = $exception->getTraceAsStringEx(); } else { $trace_string = $exception->getTraceAsString(); } if (Pie::textMode()) { $result = "{$message}\n" . "in {$file} ({$line})\n" . $trace_string; } else { if ($exception instanceof Pie_Exception_PhpError or !empty($exception->messageIsHtml)) { // do not sanitize $message } else { $message = Pie_Html::text($message); } $result = "<h1>{$message}</h1>" . "<h3>in {$file} ({$line})</h3>" . "<pre>" . $trace_string . "</pre>"; } echo $result; } $app = Pie_Config::get('pie', 'app', null); Pie::log("{$app}: Exception in " . ceil(Pie::microtime()) . "ms\n"); Pie::log("{$message}\n in {$file} ({$line})"); }
function pie_addScriptLines() { $app = Pie_Config::expect('pie', 'app'); $uri = Pie_Dispatcher::uri(); $proxies_json = json_encode(Pie_Config::get('pie', 'proxies', array())); $uri_json = json_encode($uri->toArray()); $url = Pie_Request::url(); $url_json = json_encode($url); $proxy_url_json = json_encode(Pie_Uri::url($url)); $base_url = json_encode(Pie_Request::baseUrl()); Pie_Response::addScriptLine(<<<EOT // pie {{ \t\tPie.info = { \t\t\t"proxies": {$proxies_json}, \t\t\t"uri": {$uri_json}, \t\t\t"url": {$url_json}, \t\t\t"proxyUrl": {$proxy_url_json}, \t\t\t"baseUrl": {$base_url} \t\t}; EOT ); $uris = Pie_Config::get('pie', 'javascript', 'uris', array()); $urls = array(); foreach ($uris as $u) { $urls["{$u}"] = Pie_Uri::url("{$u}"); } $urls_json = json_encode($urls); Pie_Response::addScriptLine("\t\tPie.urls = {$urls_json};"); // Export more variables to inline js $app = Pie_Config::expect('pie', 'app'); $app_json = json_encode($app); Pie_Response::addScriptLine("\t\tPie.app = {$app_json};\n" . "// }} pie"); $snf = Pie_Config::get('pie', 'session', 'nonceField', 'nonce'); $nonce = isset($_SESSION[$snf]) ? $_SESSION[$snf] : null; if ($nonce) { $nonce_json = json_encode($nonce); Pie_Response::addScriptLine("\t\tPie.nonce = {$nonce_json};"); } }
/** * Returns what the local filename of a local URL would typically be without any routing. * If not found under docroot, also checks various aliases. * * @param string $url * The url to translate, whether local or an absolute url beginning with the base URL * @return string * The complete filename of the file or directory. * It may not point to an actual file or directory, so use file_exists() or realpath();s */ static function filenamefromUrl($url) { if (Pie_Valid::url($url)) { // This is an absolute URL. Get only the part after the base URL // Run it through proxies first $url = self::proxyDestination($url); $local_url = Pie_Request::tail($url); } else { $local_url = $url; } $parts = explode('?', $local_url); $local_url = $parts[0]; if ($local_url == '' || $local_url[0] != '/') { $local_url = '/' . $local_url; } // Try various aliases first $aliases = Pie_Config::get('pie', 'aliases', array()); foreach ($aliases as $alias => $path) { $alias_len = strlen($alias); if (substr($local_url, 0, $alias_len) == $alias) { return $path . substr($local_url, $alias_len); } } // Otherwise, we should use the document root. $docroot_dir = self::documentRoot(); return $docroot_dir . $local_url; }
/** * Loads the configuration and plugins in the right order */ static function configure() { Pie_Config::load('config/pie.json'); // Get the app config, but don't load it yet $app_p = new Pie_Parameters(); $app_p->load('config/app.json'); $app_p->load('local/app.json'); // Load all the plugin config files first $paths = explode(PS, get_include_path()); $plugins = $app_p->get('pie', 'plugins', array()); foreach ($plugins as $plugin) { $plugin_path = Pie::realPath('plugins' . DS . $plugin); if (!$plugin_path) { throw new Pie_Exception_MissingPlugin(compact('plugin')); } Pie_Config::load($plugin_path . DS . 'config' . DS . 'plugin.json'); array_splice($paths, 1, 0, array($plugin_path)); $PLUGIN = strtoupper($plugin); if (!defined($PLUGIN . '_PLUGIN_DIR')) { define($PLUGIN . '_PLUGIN_DIR', $plugin_path); } if (!defined($PLUGIN . '_PLUGIN_CONFIG_DIR')) { define($PLUGIN . '_PLUGIN_CONFIG_DIR', $plugin_path . DS . 'config'); } if (!defined($PLUGIN . '_PLUGIN_CLASSES_DIR')) { define($PLUGIN . '_PLUGIN_CLASSES_DIR', $plugin_path . DS . 'classes'); } if (!defined($PLUGIN . '_PLUGIN_FILES_DIR')) { define($PLUGIN . '_PLUGIN_FILES_DIR', $plugin_path . DS . 'files'); } if (!defined($PLUGIN . '_PLUGIN_HANDLERS_DIR')) { define($PLUGIN . '_PLUGIN_HANDLERS_DIR', $plugin_path . DS . 'handlers'); } if (!defined($PLUGIN . '_PLUGIN_PLUGINS_DIR')) { define($PLUGIN . '_PLUGIN_PLUGINS_DIR', $plugin_path . DS . 'plugins'); } if (!defined($PLUGIN . '_PLUGIN_SCRIPTS_DIR')) { define($PLUGIN . '_PLUGIN_SCRIPTS_DIR', $plugin_path . DS . 'scripts'); } if (!defined($PLUGIN . '_PLUGIN_TESTS_DIR')) { define($PLUGIN . '_PLUGIN_TESTS_DIR', $plugin_path . DS . 'tests'); } if (!defined($PLUGIN . '_PLUGIN_WEB_DIR')) { define($PLUGIN . '_PLUGIN_WEB_DIR', $plugin_path . DS . 'web'); } } set_include_path(implode(PS, $paths)); // Now, we can merge in our app's config Pie_Config::merge($app_p); // Now, load any other files we were supposed to load $config_files = Pie_Config::get('pie', 'configFiles', array()); foreach ($config_files as $cf) { Pie_Config::load($cf); } $script_files = Pie_Config::get('pie', 'scriptFiles', array()); foreach ($script_files as $cf) { Pie::includeFile($cf); } }
static function facebook($key) { if (!isset($key)) { if (isset(self::$facebook)) { return self::$facebook; } } if (isset(self::$facebooks[$key])) { return self::$facebooks[$key]; } $fb_prefix = 'fb_sig_'; // Get the facebook object from POST, if any if (isset($_POST[$fb_prefix . 'app_id'])) { $app_id = $_POST[$fb_prefix . 'app_id']; $fb_apps = Pie_Config::get('users', 'facebookApps', array()); $fb_info = null; $fb_key = null; foreach ($fb_apps as $key => $a) { if (isset($a['appId']) and $a['appId'] == $app_id) { $fb_info = $a; $fb_key = $key; break; } } if (isset($fb_info['apiKey']) && isset($fb_info['secret'])) { $facebook = new Facebook($fb_info['apiKey'], $fb_info['secret']); Users::$facebook = $facebook; Users::$facebooks[$app_id] = $facebook; Users::$facebooks[$key] = $facebook; return $facebook; } } $fb_info = Pie_Config::get('users', 'facebookApps', $key, array()); if ($fb_info) { if (isset($_COOKIE[$fb_info['apiKey'] . '_user']) and isset($_COOKIE[$fb_info['apiKey'] . '_session_key'])) { $facebook = new Facebook($fb_info['apiKey'], $fb_info['secret']); $facebook->set_user($_COOKIE[$fb_info['apiKey'] . '_user'], $_COOKIE[$fb_info['apiKey'] . '_session_key']); Users::$facebooks[$fb_info['appId']] = $facebook; Users::$facebooks[$key] = $facebook; } return $facebook; } // Otherwise, this facebook object isn't there return null; }
/** * Returns connection details for a connection * @param $name * @return array|false */ static function getConnection($name) { if (class_exists('Pie_Config')) { return Pie_Config::get('db', 'connections', $name, null); } // Else standalone, no Pie if (!isset(self::$connections[$name])) { return null; } return self::$connections[$name]; }
/** * Starts the process of adding a mobile to a saved user object. * Also modifies and saves this user object back to the database. * @param string $mobile_number * The mobile number to add. * @param string $activation_mobile_view * The view to use for the body of the activation mobile to send. * @param boolean $html * Defaults to true. Whether to send as HTML mobile. * @param array $fields * An array of additional fields to pass to the mobile view. * @return boolean * Returns true on success. * Returns false if this mobile number is already verified for this user. * @throws Pie_Exception_WrongType * If the mobile number is in an invalid format, this is thrown. * @throws Users_Exception_AlreadyVerified * If the mobile number already exists and has been verified for * another user, then this exception is thrown. */ function addMobile($mobile_number, $activation_mobile_subject = null, $activation_mobile_view = null, $html = true, $fields = array()) { // TODO: Implement Users_Mobile::sendMessage if (!Pie_Valid::mobile($mobile_number)) { throw new Pie_Exception_WrongValue(array('field' => 'Mobile phone', 'range' => 'a valid number'), 'mobile_number'); } Pie::event('users/validate/mobile_number', array('mobile_number' => &$mobile_number)); $m = new Users_Mobile(); $m->number = $mobile_number; if ($m->retrieve() and $m->state !== 'unverified') { if ($m->user_id === $this->id) { return false; } // Otherwise, say it's verified for another user, // even if it unsubscribed or was suspended. throw new Users_Exception_AlreadyVerified(array('key' => $m->number, 'user_id' => $m->user_id), 'mobile_number'); } // If we are here, then the mobile record either // doesn't exist, or hasn't been verified yet. // In either event, update the record in the database, // and re-send the mobile. $minutes = Pie_Config::get('users', 'activationCodeExpires', 60 * 24 * 7); $m->state = 'unverified'; $m->user_id = $this->id; $m->activation_code = Pie_Utils::unique(5); $m->activation_code_expires = new Db_Expression("CURRENT_TIMESTAMP + INTERVAL {$minutes} MINUTE"); $m->auth_code = md5(microtime() + mt_rand()); $m->save(); if (!isset($activation_message_view)) { $activation_message_view = Pie_Config::get('users', 'activationMessageView', 'users/message/activation.php'); } $fields2 = array_merge($fields, array('user' => $this, 'message' => $m)); $m->sendMessage($activation_mobile_view, $fields2, array('html' => $html)); Pie::event('users/addMobile', compact('mobile_number'), 'after'); }
function items_addPhoto_response_result() { return Pie_Config::get('items', 'addPhoto', 'result', 'added') . ' ' . Pie_Config::get('items', 'addPhoto', 'item_id', null) . ' ' . Pie_Config::get('items', 'addPhoto', 'state', null); }
/** * Converts an exception or array of exceptions to an array * @param Exception|array $exceptions * The exception object or array of exceptions to convert * @return array */ static function toArray($exceptions) { if (empty($exceptions)) { return array(); } $array_was_passed = true; if (!is_array($exceptions)) { $exceptions = array($exceptions); $array_was_passed = false; } $results = array(); $show_fal = Pie_Config::get('pie', 'exception', 'showFileAndLine', true); $show_trace = Pie_Config::get('pie', 'exception', 'showTrace', true); foreach ($exceptions as $e) { if (!$e instanceof Exception) { continue; } $message = $e->getMessage(); $code = $e->getCode(); if ($show_fal) { $line = $e->getLine(); $file = $e->getFile(); } if ($show_trace) { if (is_callable(array($e, 'getTraceEx'))) { $trace = $e->getTraceEx(); } else { $trace = $e->getTrace(); } } $fields = null; if (is_callable(array($e, 'inputFields'))) { $fields = $e->inputFields(); } $results[] = compact('message', 'code', 'line', 'file', 'trace', 'fields'); } if ($array_was_passed) { return $results; } else { $ret = reset($results); return $ret ? $ret : array(); } }
<?php /** * This file gets included when someone wants to use the Facebook class */ set_include_path(get_include_path() . PS . dirname(__FILE__) . DS . 'Facebook'); if (Pie_Config::get('users', 'facebook', 'new', false)) { include 'facebook_new.php'; } else { include 'facebook.php'; }
/** * Use this to determine whether or not the request is to be treated * as a POST request by our application. * @return boolean * Returns true if the request should be treated as a POST. */ static function isPost() { static $result; if (!isset($result)) { $result = Pie::event('pie/request/isPost', array(), 'before'); } if (!isset($result)) { $query_param = Pie_Config::get('pie', 'queryField', '_pie'); if (isset($_REQUEST[$query_param]['post'])) { return true; } } return !empty($_POST); }
static function setNonce() { $snf = Pie_Config::get('pie', 'session', 'nonceField', 'nonce'); self::start(); if (!isset($_SESSION[$snf])) { $_SESSION[$snf] = md5(mt_rand() . microtime()); } }
/** * Default pie/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 pie_response($params) { extract($params); /** * @var Exception $exception * @var array $errors */ // Redirect to success page, if requested. $is_ajax = Pie_Request::isAjax(); if (empty($errors) and empty($exception)) { if (!$is_ajax and isset($_REQUEST['_pie']['onSuccess'])) { $on_success = $_REQUEST['_pie']['onSuccess']; if (Pie_Config::get('pie', 'response', 'onSuccessShowFrom', true)) { $on_success = Pie_Uri::url($on_success . '?_pie[fromSuccess]=' . Pie_Dispatcher::uri()); } Pie_Response::redirect($on_success); return; } } // Get the requested module $uri = Pie_Dispatcher::uri(); if (!isset($module)) { $module = $uri->module; if (!isset($module)) { $module = 'pie'; Pie_Dispatcher::uri()->module = 'pie'; } } // Get the main module (the app) $app = Pie_Config::expect('pie', 'app'); // Add some javascript to inform the front end of important URLs Pie::event('pie/addScriptLines'); // What to do if this is an AJAX request if ($is_ajax) { $slot_names = Pie_Request::slotNames(); if (!isset($slot_names)) { $slot_names = Pie_Config::get($module, 'response', 'slotNames', array('content' => null, 'dashboard' => null, 'title' => null, 'notices' => null)); } $slots = array(); $stylesheets = array(); $stylesInline = array(); $scripts = array(); $scriptLines = array(); if (is_array($slot_names)) { foreach ($slot_names as $slot_name => $v) { $slots[$slot_name] = Pie_Response::fillSlot($slot_name, 'default'); $stylesheets[$slot_name] = Pie_Response::stylesheetsArray($slot_name); $stylesInline[$slot_name] = Pie_Response::stylesInline($slot_name); $scripts[$slot_name] = Pie_Response::scriptsArray($slot_name); $scriptLines[$slot_name] = Pie_Response::scriptLines($slot_name); } } $timestamp = microtime(true); $echo = Pie_Request::contentToEcho(); // Render a JSON layout for ajax $to_encode = compact('slots', 'stylesheets', 'stylesInline', 'scripts', 'scriptLines', 'timestamp', 'echo'); // Cut down on the response size foreach (array('slots', 'stylesheets', 'stylesInline', 'scripts', 'scriptLines') as $f) { $is_empty = true; if (is_array($to_encode[$f])) { foreach ($to_encode[$f] as $k => $v) { if (isset($v)) { $is_empty = false; } else { unset($to_encode[$f][$k]); } } } else { if (!empty($to_encode[$f])) { $is_empty = false; } } if ($is_empty) { unset($to_encode[$f]); } } switch (strtolower($is_ajax)) { case 'json': default: $json = json_encode($to_encode); $callback = Pie_Request::callback(); echo $callback ? "{$callback}({$json})" : $json; } return; } // If this is a request for a regular webpage, // fill the usual slots and render a layout. // Attach stylesheets and scripts if (Pie_Request::accepts('text/fbml')) { Pie_Response::addStylesheet("css/fbml.css"); Pie_Response::addScript('plugins/pie/fbjs/Pie.fb.js'); } else { Pie_Response::addStylesheet("css/html.css"); Pie_Response::addScript('plugins/pie/js/Pie.js'); } // Get all the usual slots for a webpage $slot_names = Pie_Config::get($module, 'response', 'slotNames', array('content' => null, 'dashboard' => null, 'title' => null, 'notices' => null)); $slots = array(); foreach ($slot_names as $sn => $v) { $slots[$sn] = Pie_Response::fillSlot($sn, 'default'); } $output = Pie_Response::output(); if (isset($output)) { if ($output === true) { return; } if (is_string($output)) { echo $output; } return; } if (Pie_Request::accepts('text/fbml')) { // Render a full FBML layout $layout_view = Pie_Config::get($app, 'response', 'layout_fbml', "{$app}/layout/fbml.php"); echo Pie::view($layout_view, $slots); } else { // Render a full HTML layout $layout_view = Pie_Config::get($app, 'response', 'layout_html', "{$app}/layout/html.php"); echo Pie::view($layout_view, $slots); } }
/** * Gets the url and filename of a themed file * @param string $file_path * Basically the subpath of the file underneath the web or theme directory */ static function themedUrlAndFilename($file_path) { $filename = false; $theme_url = Pie_Uri::url(self::themeUrl()); $theme_urls = Pie_Config::get('pie', 'theme_urls', array(null)); if (!Pie_Valid::url($file_path)) { $c = count($theme_urls); if ($c > 1) { // At least two theme URLs have been loaded // Do the cascade for ($i = $c - 1; $i >= 0; --$i) { try { $filename = Pie_Uri::filenameFromUrl($theme_urls[$i] . '/' . $file_path); } catch (Exception $e) { continue; } if (file_exists($filename)) { $theme_url = $theme_urls[$i]; break; } } } $file_path = $theme_url . '/' . $file_path; } if (empty($filename)) { try { $filename = Pie_Uri::filenameFromUrl($file_path); } catch (Exception $e) { $filename = null; } } return array($file_path, $filename); }
/** * Use this for validating the nonce * @param boolean $throw_if_invalid * Optional. If true, throws an exception if the nonce is invalid. */ static function nonce($throw_if_invalid = false) { $snf = Pie_Config::get('pie', 'session', 'nonceField', 'nonce'); if (isset($_SESSION['pie'][$snf])) { if (!isset($_REQUEST['_pie'][$snf]) or $_SESSION['pie'][$snf] != $_REQUEST['_pie'][$snf]) { if (!$throw_if_invalid) { return false; } $message = Pie_Config::get('pie', 'session', 'nonceMessage', "Your session has expired (nonce mismatch). Perhaps you logged in as a different user?"); throw new Pie_Exception_FailedValidation(compact('message')); } } return true; }
private static function do_dump(&$var, $var_name = NULL, $indent = NULL, $reference = NULL, $as_text = false) { static $n = null; if (!isset($n)) { $n = Pie_Config::get('pie', 'newline', "\n"); } $do_dump_indent = $as_text ? " " : "<span style='color:#eeeeee;'>|</span> "; $reference = $reference . $var_name; $keyvar = 'the_do_dump_recursion_protection_scheme'; $keyname = 'referenced_object_name'; $max_indent = self::$var_dump_max_levels; if (strlen($indent) >= strlen($do_dump_indent) * $max_indent) { echo $indent . $var_name . " (...){$n}"; return; } if (is_array($var) && isset($var[$keyvar])) { $real_var =& $var[$keyvar]; $real_name =& $var[$keyname]; $type = ucfirst(gettype($real_var)); if ($as_text) { echo "{$indent}{$var_name}<{$type}> = {$real_name}{$n}"; } else { echo "{$indent}{$var_name} <span style='color:#a2a2a2'>{$type}</span> = <span style='color:#e87800;'>&{$real_name}</span><br>"; } } else { $var = array($keyvar => $var, $keyname => $reference); $avar =& $var[$keyvar]; $type = ucfirst(gettype($avar)); if ($type == "String") { $type_color = "green"; } elseif ($type == "Integer") { $type_color = "red"; } elseif ($type == "Double") { $type_color = "#0099c5"; $type = "Float"; } elseif ($type == "Boolean") { $type_color = "#92008d"; } elseif ($type == "NULL") { $type_color = "black"; } else { $type_color = '#92008d'; } if (is_array($avar)) { $count = count($avar); if ($as_text) { echo "{$indent}" . ($var_name ? "{$var_name} => " : "") . "<{$type}>({$count}){$n}{$indent}({$n}"; } else { echo "{$indent}" . ($var_name ? "{$var_name} => " : "") . "<span style='color:#a2a2a2'>{$type} ({$count})</span><br>{$indent}(<br>"; } $keys = array_keys($avar); foreach ($keys as $name) { $value =& $avar[$name]; $display_name = is_string($name) ? "['" . addslashes($name) . "']" : "[{$name}]"; self::do_dump($value, $display_name, $indent . $do_dump_indent, $reference, $as_text); } if ($as_text) { echo "{$indent}){$n}"; } else { echo "{$indent})<br>"; } } elseif (is_object($avar)) { $class = get_class($avar); if ($as_text) { echo "{$indent}{$var_name}<{$type}>[{$class}]{$n}{$indent}({$n}"; } else { echo "{$indent}{$var_name} <span style='color:{$type_color}'>{$type} [{$class}]</span><br>{$indent}(<br>"; } if ($avar instanceof Exception) { $code = $avar->getCode(); $message = addslashes($avar->getMessage()); echo "{$indent}{$do_dump_indent}" . "code: {$code}, message: \"{$message}\""; if ($avar instanceof Pie_Exception) { echo " inputFields: " . implode(', ', $avar->inputFIelds()); } echo $as_text ? $n : "<br />"; } if (class_exists('Pie_Parameters') and $avar instanceof Pie_Parameters) { $getall = $avar->getAll(); self::do_dump($getall, "", $indent . $do_dump_indent, $reference, $as_text); } else { if ($avar instanceof Pie_Uri) { $arr = $avar->toArray(); self::do_dump($arr, 'fields', $indent . $do_dump_indent, $reference, $as_text); self::do_dump($route_pattern, 'route_pattern', $indent . $do_dump_indent, $reference, $as_text); } } if ($avar instanceof Db_Row) { foreach ($avar as $name => $value) { $modified = $avar->wasModified($name) ? "<span style='color:blue'>*</span>:" : ''; self::do_dump($value, "{$name}{$modified}", $indent . $do_dump_indent, $reference, $as_text); } } else { foreach ($avar as $name => $value) { self::do_dump($value, "{$name}", $indent . $do_dump_indent, $reference, $as_text); } } if ($as_text) { echo "{$indent}){$n}"; } else { echo "{$indent})<br>"; } } elseif (is_int($avar)) { $avar_len = strlen((string) $avar); if ($as_text) { echo sprintf("{$indent}{$var_name} = <{$type}(%d)>{$avar}{$n}", $avar_len); } else { echo sprintf("{$indent}{$var_name} = <span style='color:#a2a2a2'>{$type}(%d)</span>" . " <span style='color:{$type_color}'>{$avar}</span><br>", $avar_len); } } elseif (is_string($avar)) { $avar_len = strlen($avar); if ($as_text) { echo sprintf("{$indent}{$var_name} = <{$type}(%d)> ", $avar_len), $avar, "{$n}"; } else { echo sprintf("{$indent}{$var_name} = <span style='color:#a2a2a2'>{$type}(%d)</span>", $avar_len) . " <span style='color:{$type_color}'>" . Pie_Html::text($avar) . "</span><br>"; } } elseif (is_float($avar)) { $avar_len = strlen((string) $avar); if ($as_text) { echo sprintf("{$indent}{$var_name} = <{$type}(%d)>{$avar}{$n}", $avar_len); } else { echo sprintf("{$indent}{$var_name} = <span style='color:#a2a2a2'>{$type}(%d)</span>" . " <span style='color:{$type_color}'>{$avar}</span><br>", $avar_len); } } elseif (is_bool($avar)) { $v = $avar == 1 ? "TRUE" : "FALSE"; if ($as_text) { echo "{$indent}{$var_name} = <{$type}>{$v}{$n}"; } else { echo "{$indent}{$var_name} = <span style='color:#a2a2a2'>{$type}</span>" . " <span style='color:{$type_color}'>{$v}</span><br>"; } } elseif (is_null($avar)) { if ($as_text) { echo "{$indent}{$var_name} = NULL{$n}"; } else { echo "{$indent}{$var_name} = " . " <span style='color:{$type_color}'>NULL</span><br>"; } } else { $avar_len = strlen((string) $avar); if ($as_text) { echo sprintf("{$indent}{$var_name} = <{$type}(%d)>{$avar}{$n}", $avar_len); } else { echo sprintf("{$indent}{$var_name} = <span style='color:#a2a2a2'>{$type}(%d)</span>", $avar_len) . " <span style='color:{$type_color}'>" . gettype($avar) . "</span><br>"; } } $var = $var[$keyvar]; } }
/** * Generates base classes of the models, and if they don't exist, * skeleton code for the models themselves. * Use it only after you have made changes to the database schema. * You shouldn't be using it on every request. * @param string $conn_name * The name of a previously registered connection. * @param string $directory * The directory in which to generate the files. * If the files already exist, they are not overwritten, * unless they are inside the "Base" subdirectory. * If the "Base" subdirectory does not exist, it is created. * @param string $classname_prefix * The prefix to prepend to the Base class names. * If not specified, prefix becomes "Conn_Name_", * where conn_name is the name of the connection. * @throws Exception * If the $connection is not registered, or the $directory * does not exist, this function throws an exception. */ function generateModels($directory, $classname_prefix = null) { if (!file_exists($directory)) { throw new Exception("Directory {$directory} does not exist."); } $conn_name = $this->connectionName(); $conn = Db::getConnection($conn_name); $prefix = empty($conn['prefix']) ? '' : $conn['prefix']; $prefix_len = strlen($prefix); if (!isset($classname_prefix)) { $classname_prefix = isset($conn_name) ? $conn_name . '_' : ''; } $rows = $this->rawQuery('SHOW TABLES')->execute()->fetchAll(); if (class_exists('Pie_Config')) { $ext = Pie_Config::get('pie', 'extensions', 'class', 'php'); } else { $ext = 'php'; } $table_classes = array(); foreach ($rows as $row) { $table_name = $row[0]; $table_name_base = substr($table_name, $prefix_len); $table_name_prefix = substr($table_name, 0, $prefix_len); if (empty($table_name_base) or $table_name_prefix != $prefix) { continue; } // no class generated $class_name = null; $base_class_string = $this->codeForModelBaseClass($table_name, $directory, $classname_prefix, $class_name); // sets the $class_name variable if (empty($class_name)) { continue; } // no class generated $class_string = <<<EOT <?php /** * Class representing {$table_name_base} rows. * You can create an object of this class either to * access its non-static methods, or to actually * represent a {$table_name_base} row in the {$conn_name} database. * * This description should be revised and expanded. * * @package {$conn_name} */ class {$class_name} extends Base_{$class_name} { \t/** \t * The setUp() method is called the first time \t * an object of this class is constructed. \t */ \tfunction setUp() \t{ \t\tparent::setUp(); \t\t// INSERT YOUR CODE HERE \t\t// e.g. \$this->hasMany(...) and stuff like that. \t} \t \t/** \t * Implements the __set_state method, so it can work with \t * with var_export and be re-imported successfully. \t */ \tstatic function __set_state(array \$array) { \t\t\$result = new {$class_name}(); \t\tforeach(\$array as \$k => \$v) \t\t\t\$result->\$k = \$v; \t\treturn \$result; \t} }; EOT; $class_name_parts = explode('_', $class_name); $class_filename = $directory . DS . implode(DS, $class_name_parts) . '.php'; $base_class_filename = $directory . DS . 'Base' . DS . implode(DS, $class_name_parts) . '.php'; // overwrite base class file if necessary, but not the class file Db_Utils::saveTextFile($base_class_filename, $base_class_string); if (!file_exists($class_filename)) { Db_Utils::saveTextFile($class_filename, $class_string); } $table_classes[] = $class_name; } // Generate the "module model" base class file $table_classes_exported = var_export($table_classes, true); if (!empty($conn_name)) { $class_name = Db::generateTableClassName($conn_name); $class_name_parts = explode('_', $class_name); $class_filename = $directory . DS . implode(DS, $class_name_parts) . '.php'; $base_class_filename = $directory . DS . 'Base' . DS . implode(DS, $class_name_parts) . '.php'; $base_class_string = <<<EOT <?php /** * Autogenerated base class for the {$conn_name} model. * * Don't change this file, since it can be overwritten. * Instead, change the {$class_name}.php file. * * @package {$conn_name} */ abstract class Base_{$class_name} { \tstatic \$table_classes = {$table_classes_exported}; \t/** @return Db_Mysql */ \tstatic function db() \t{ \t\treturn Db::connect('{$conn_name}'); \t} \tstatic function connectionName() \t{ \t\treturn '{$conn_name}'; \t} }; EOT; $class_string = <<<EOT <?php /** * Static methods for the {$conn_name} models. * This description should be revised and expanded. * * @package {$conn_name} */ abstract class {$class_name} extends Base_{$class_name} { \t/** \t * This is where you would place all the \t * static methods for the models, the ones \t * that don't strongly pertain to a particular row \t * or table. \t */ }; EOT; // overwrite base class file if necessary, but not the class file Db_Utils::saveTextFile($base_class_filename, $base_class_string); if (!file_exists($class_filename)) { Db_Utils::saveTextFile($class_filename, $class_string); } } }
/** * Connect to database * @method dbConnect * @static * @return {boolean} */ static function dbConnect() { if (isset(self::$db)) { return false; } $driver_options = array('3' => 2); $arr = Pie_Config::get('db', 'connections', 'rs', false); if (!$arr) { throw new Exception("Missing connection details for rs"); } extract($arr); self::$db = new PDO($dsn, $username, $password, $driver_options); if (!self::$db) { throw new Exception("Could not connect to db"); } return true; }
/** * Dispatches a URI for internal processing. * Usually called by a front controller. * @param mixed $uri * Optional. You can pass a custom URI to dispatch. Otherwise, PIE will attempt * to route the requested URL, if any. * @param array $check * Optional. Pass array() to skip checking whether the URI can be obtained * as a result of routing some URL. * @return boolean */ static function dispatch($uri = null, $check = array('accessible')) { if (!is_array($check)) { $check = array('accessible'); } if (isset($uri)) { if (in_array('accessible', $check)) { if (!Pie_Uri::url($uri)) { // We shouldn't dispatch to this URI $uri = Pie_Uri::from(array()); } } self::$uri = Pie_Uri::from($uri); } else { self::$uri = Pie_Request::uri(); } // if file or dir is requested, try to serve it $served = false; $skip = Pie_Config::get('pie', 'dispatcherSkipFilename', false); $filename = $skip ? false : Pie_Request::filename(); if ($filename) { if (is_dir($filename)) { $served = Pie::event("pie/dir", compact('filename', 'routed_uri')); $dir_was_served = true; } else { $served = Pie::event("pie/file", compact('filename', 'routed_uri')); $dir_was_served = false; } } // if response was served, then return if ($served) { self::result($dir_was_served ? "Dir served" : "File served"); return true; } // This loop is for forwarding $max_forwards = Pie_Config::get('pie', 'maxForwards', 10); for ($try = 0; $try < $max_forwards; ++$try) { // Make an array from the routed URI $routed_uri_array = array(); if (self::$uri instanceof Pie_Uri) { $routed_uri_array = self::$uri->toArray(); } // If no module was found, then respond with noModule and return if (!isset(self::$uri->module)) { Pie::event("pie/noModule", $routed_uri_array); // should echo things self::result("No module"); return false; } $module = self::$uri->module; // Implement restricting of modules we are allowed to access $routed_modules = Pie_Config::get('pie', 'routedModules', null); if (isset($routed_modules)) { if (!in_array($module, $routed_modules)) { Pie::event('pie/notFound', $routed_uri_array); // should echo things self::result("Unknown module"); return false; } } else { if (!Pie::realPath("handlers/{$module}")) { Pie::event('pie/notFound', $routed_uri_array); // should echo things self::result("Unknown module"); return false; } } try { // Fire a pure event, for aggregation etc if (!in_array('pie/prepare', self::$skip)) { Pie::event('pie/prepare', $routed_uri_array, true); } // Perform validation if (!in_array('pie/validate', self::$skip)) { Pie::event('pie/validate', $routed_uri_array); // Check if any errors accumulated if (Pie_Response::getErrors()) { // There were validation errors -- render a response self::errors(null, $module, null); self::result('Validation errors'); return false; } } // Time to instantiate some app objects from the request if (!in_array('pie/objects', self::$skip)) { Pie::event('pie/objects', $routed_uri_array, true); } // We might want to reroute the request if (!in_array('pie/reroute', self::$skip)) { $stop_dispatch = Pie::event('pie/reroute', $routed_uri_array, true); if ($stop_dispatch) { self::result("Stopped dispatch"); return false; } } if (Pie_Request::isPost()) { if (!in_array('pie/post', self::$skip)) { // Make some changes to server state, possibly Pie::event('pie/post', $routed_uri_array); } } // Time to instantiate some app objects from the request if (!in_array('pie/analytics', self::$skip)) { Pie::event('pie/analytics', $routed_uri_array, true); } // Start buffering the response, unless otherwise requested if ($handler = Pie_Response::isBuffered()) { $ob = new Pie_OutputBuffer($handler); } // Generate and render a response Pie::event("pie/response", $routed_uri_array); if (!empty($ob)) { $ob->endFlush(); } self::result("Served response"); return true; } catch (Pie_Exception_DispatcherForward $e) { // Go again, this time with a different URI. self::$uri = Pie_Uri::from($e->uri); if (is_array($e->skip)) { self::$skip = $e->skip; } else { // Don't process the POST fields this time around self::$skip = array('pie/post'); } // We'll be handling errors anew self::$handling_errors = false; } catch (Pie_Exception_DispatcherErrors $e) { if (!empty($ob)) { $partial_response = $ob->getClean(); } else { $partial_response = null; } self::errors(null, $module, $partial_response); self::result("Rendered errors"); return true; } catch (Exception $exception) { if (!empty($ob)) { $partial_response = $ob->getClean(); } else { $partial_response = null; } self::errors($exception, $module, $partial_response); self::result("Exception occurred"); return false; } } // If we are here, we have done forwarding too much throw new Pie_Exception_Recursion(array('function_name' => 'Dispatcher::forward()')); }