/** * Создание пользователя * @return int userId - код нового пользователя */ public final function createUser(RegFormData $data) { $email = PsCheck::email($data->getUserMail()); //Проверим, что пользователь с таким email ещё не заведён check_condition(!$this->hasMail($email), "Пользователь с почтой [{$email}] уже зарегистрирован"); //Подготовим поля для вставки $params[self::FIELD_NAME] = $data->getUserName(); $params[self::FIELD_SEX] = $data->getSex(); $params[self::FIELD_EMAIL] = $email; $params[self::FIELD_PASSWD] = self::hashPassword($data->getPassword()); $params[self::FIELD_B_ADMIN] = 0; $params[self::FIELD_B_CAN_LOGIN] = 1; $params[] = Query::assocParam(self::FIELD_DT_REG, 'UNIX_TIMESTAMP()', false); //Выполняем вставку $userId = $this->register($this->insert(Query::insert('users', $params))); //Сохраним данные пользователя в аудит UserAudit::inst()->afterRegistered($userId, array_filter_keys($this->getUserDataById($userId), self::$SKIP_AUDIT_ON_CREATE_FIELDS)); //Возвращаем код пользователя return $userId; }
public function resolve(Request $request, Response $response) { $path = $this->srcPath . $request->uri('path') . '.url'; // Check if target file is a proxy. if (!is_file($path)) { return; } $cacheTarget = parse_ini_file($path); $cacheTarget = @$cacheTarget['URL']; unset($path); if (!$cacheTarget) { Log::warning('Proxy file has not URL parameter.', array('requestUri' => $request->uri(), 'proxyFile' => $request->uri('path') . '.uri')); $response->status(502); // Bad Gateway return; } /*! Cache Header Notes * * # Cache-Control * [public | private] Cacheable when public, otherwise the client is responsible for caching. * [no-cache( \w+)?] When no fields are specified, the whole thing must revalidate everytime, * otherwise cache it except specified fields. * [no-store] Ignore caching and pipe into output. * [max-age=\d+] Seconds before this cache is meant to expire, this overrides Expires header. * [s-maxage=\d+] Overrides max-age and Expires header, behaves just like max-age. * (This is for CDN and we are using it.) * [must-revalidate] Tells those CDNs which are intended to serve stale contents to revalidate every time. * [proxy-revalidate] Like the "s-" version of max-age, a "must-revalidate" override only for CDN. * [no-transform] Some CDNs will optimize images and other formats, this "opt-out" of it. * * # Expires * RFC timestamp for an absolute cache expiration, overridden by Cache-Control header. * * # ETag * Hash of anything, weak ETags is not supported at this moment. * * # vary * Too much fun inside and we are too serious about caching, ignore this. * * # pragma * This guy is too old to recognize. * [no-cache] Only this is known nowadays and is already succeed by Cache-Control: no-cache. * */ // note; Use "cache-meta://" scheme for header and cache meta info, for performance. // 1. Check if cache exists. $cache = (array) Cache::get("cache-meta://{$cacheTarget}"); // Cache expiration, in seconds. // expires = ( s-maxage || max-age || Expires ); if (@$cache['expires'] && time() > $cache['expires']) { Cache::delete("cache-meta://{$cacheTarget}"); Cache::delete("cache://{$cacheTarget}"); $cache = null; } // - If not exists, make normal request to remote server. // - If exists, make conditional request to remote server. // - Revalidation, we can skip this request and serve the content if false. // revalidates = ( Cache-Control:proxy-revalidate || Cache-Control:must-revalidate ) if (!$cache || @$cache['revalidates']) { $_request = array('uri' => $cacheTarget); if ($cache) { // Last-Modified if (@$cache['headers']['Last-Modified']) { $_request['headers']['If-Modified-Since'] = $cache['Last-Modified']; } // Entity-Tag if (@$cache['headers']['ETag'] && strpos($cache['headers']['ETag'], 'W\\') !== 0) { $_request['headers']['If-None-Match'] = $cache['ETag']; } } else { $cache = array(); } // Make the request $_response = new Response(array('autoOutput' => false)); (new Request($_request))->send(null, $_response); unset($_request); // parse headers into cache settings. if (in_array($_response->status(), array(200, 304))) { $res = preg_split('/\\s*,\\s*/', util::unwrapAssoc($_response->header('Cache-Control'))); $res = array_reduce($res, function ($res, $value) { // todo; Take care of no-cache with field name. if (strpos($value, '=') > 0) { $value = explode('=', $value); $res[$value[0]] = $value[1]; } else { $res[$value] = true; } return $res; }, array()); // private, no-store, no-cache if (@$res['private'] || @$res['no-store'] || @$res['no-cache']) { // note; in case the upstream server change this to uncacheable Cache::delete("cache-meta://{$cacheTarget}"); Cache::delete("cache://{$cacheTarget}"); $_response->clearBody(); } if ($_response->status() == 200 && $_response->body()) { $cache['contents'] = $_response->body(); } // expires = ( s-maxage || max-age || Expires ); if (@$res['s-maxage']) { $cache['expires'] = time() + $res['s-maxage']; } elseif (@$res['max-age']) { $cache['expires'] = time() + $res['max-age']; } else { $res = util::unwrapAssoc($_response->header('Expires')); if ($res) { $cache['expires'] = strtotime($res); } } // revalidates = ( Cache-Control:proxy-revalidate || Cache-Control:must-revalidate ) if (@$res['proxy-revalidate'] || @$res['must-revalidate']) { $cache['revalidates'] = true; } unset($res); } $cache['headers'] = array_map('core\\Utility::unwrapAssoc', $_response->header()); // PHP does not support chunked, skip this one. unset($cache['headers']['Transfer-Encoding']); // note; If cache is to be ignored, the $cacheTarget variable will be already unset(). if (isset($cacheTarget)) { if (@$cache['contents']) { Cache::set("cache://{$cacheTarget}", $cache['contents']); } Cache::set("cache-meta://{$cacheTarget}", array_filter_keys($cache, isNot('contents'))); } unset($_response); } // note; Send cache headers regardless of the request condition. if (@$cache['headers']) { $response->clearHeaders(); foreach ($cache['headers'] as $name => $value) { $response->header($name, $value, true); } unset($name, $value); } // note; Handles conditional request $ch = array_map('core\\Utility::unwrapAssoc', (array) @$cache['headers']); $mtime = @$ch['Last-Modified'] ? strtotime($ch['Last-Modified']) : false; // Request headr: If-Modified-Since if (@$ch['Last-Modified'] && $mtime) { if (strtotime($request->header('If-Modified-Since')) >= $mtime) { return $response->status(304); } } // Request header: If-Range if ($request->header('If-Range')) { // Entity tag if (strpos(substr($request->header('If-Range'), 0, 2), '"') !== false && @$ch['ETag']) { if ($this->compareETags(@$ch['ETag'], $request->header('If-Range'))) { return $this->response()->status(304); } } elseif (strtotime($request->header('If-Range')) === $mtime) { return $this->response()->status(304); } } unset($mtime); // Request header: If-None-Match if (!$request->header('If-Modified-Since') && $request->header('If-None-Match')) { // Exists but not GET or HEAD switch ($request->method()) { case 'get': case 'head': break; default: return $this->response()->status(412); } /*! Note by Vicary @ 24 Jan, 2013 * If-None-Match means 304 when target resources exists. */ if ($request->header('If-None-Match') === '*' && @$ch['ETag']) { return $this->response()->status(304); } if ($this->compareETags(@$ch['ETag'], preg_split('/\\s*,\\s*/', $request->header('If-None-Match')))) { return $this->response()->status(304); } } // Request header: If-Match if (!$request->header('If-Modified-Since') && $request->header('If-Match')) { // Exists but not GET or HEAD switch ($request->method()) { case 'get': case 'head': break; default: return $this->response()->status(412); } if ($request->header('If-Match') === '*' && !@$ch['ETag']) { return $this->response()->status(412); } preg_match_all('/(?:^\\*$|(:?"([^\\*"]+)")(?:\\s*,\\s*(:?"([^\\*"]+)")))$/', $request->header('If-Match'), $eTags); // 412 Precondition Failed when nothing matches. if (@$eTags[1] && !in_array($eTag, (array) $eTags[1])) { return $this->response()->status(412); } } if ($cacheTarget && empty($cache['contents'])) { $cache['contents'] = Cache::get("cache://{$cacheTarget}"); } // Output the cahce content $response->send($cache['contents'], 200); }
/** * Perform cURL requests and throw appropriate exceptions. * * An array of parameters used in a curl_setopt_array, * multiple calls can be passed in. * * This function make use of curl_multi no matter it is * single request or not. * * Callbacks are used to handle results inside the array. * * $option['callbacks'] = array( * 'progress' => [Function] * , 'success' => [Function] * , 'failure' => [Function] * , 'always' => [Function] * ); * * @return void */ public static function curlRequest($options) { $options = Utility::wrapAssoc(array_values((array) $options)); $multiHandle = curl_multi_init(); // Initialize cUrl options array_walk($options, function (&$option) { // 1. Request headers $option['response'] = array('headers' => ''); $option[CURLOPT_HEADERFUNCTION] = function ($curl, $data) use(&$option) { $option['response']['headers'] .= $data; return strlen($data); }; // 2. Progress function $progressCallback =& $option['callbacks']['progress']; if ($progressCallback) { $option[CURLOPT_NOPROGRESS] = false; $option[CURLOPT_PROGRESSFUNCTION] = function () use(&$progressCallback) { if (func_num_args() == 4) { list($dSize, $dLen, $uSize, $uLen) = func_get_args(); } else { list($req, $dSize, $dLen, $uSize, $uLen) = func_get_args(); } if ($dSize || $dLen) { static $_dLen = 0; if ($_dLen != $dLen) { $_dLen = $dLen; /*! Note by Vicary @ 2.Oct.2012 * Total download size is often 0 if server doesn't * response with a Content-Length header. * * Total size guessing logic: * 1. if $dLen < 1M, assume 1M. * 2. if $dLen < 10M, assume 10M. * 3. if $dLen < 100M, assume 100M. * 4. if $dLen < 1G, assume 1G. */ if (!$dSize) { // Do not assume when size under 1K if ($dLen < 5000) { return; } elseif ($dLen < 10000000) { $dSize = 20000000; } elseif ($dLen < 100000000) { $dSize = 200000000; } elseif ($dLen < 1000000000) { $dSize = 2000000000; } else { $dSize = 20000000000; } // $dSize = $dLen / .05; } // Download progress, from 0 to 1. $progressArgs = array($dLen / $dSize, $dLen, $dSize); } } else { if ($uSize) { static $_uLen = 0; if ($_uLen != $uLen) { $_uLen = $uLen; $uSize *= -1; $uLen += $uSize; // Upload progress, from -1 to 0. $progressArgs = array($uLen / $uSize, $uLen, $uSize); } } } // Fire the event for each µSeconds. static $_tOffset = 0; $tOffset = microtime(1); if (isset($progressArgs) && $tOffset - $_tOffset > self::progressInterval()) { $_tOffset = $tOffset; Utility::forceInvoke($progressCallback, $progressArgs); } }; } unset($progressCallback); // 3. Apply cUrl options, numeric keys only. $option['handle'] = curl_init(); curl_setopt_array($option['handle'], array_filter_keys($option, 'is_int')); }); $requestIndex = 0; while ($requestIndex < self::$maximumRequests && isset($options[$requestIndex])) { curl_multi_add_handle($multiHandle, $options[$requestIndex++]['handle']); } // Start the multi request do { $status = curl_multi_exec($multiHandle, $active); /* Added by Vicary @ 6.Nov.2012 Blocks until there is a message arrives. */ curl_multi_select($multiHandle); do { $info = curl_multi_info_read($multiHandle, $queueLength); if ($info === FALSE) { continue; } $optionIndex = array_search($info['handle'], array_map(prop('handle'), $options)); if ($optionIndex === FALSE) { continue; } $curlOption =& $options[$optionIndex]; $callbacks =& $curlOption['callbacks']; // Success handler if ($info['result'] === CURLE_OK) { // Fire a 100% downloaded event. if (@$callbacks['progress']) { Utility::forceInvoke($callbacks['progress'], array(1, 1, 1)); usleep(self::progressInterval() * 1000000); } // Append HTTP status code $curlOption['status'] = curl_getinfo($info['handle'], CURLINFO_HTTP_CODE); Utility::forceInvoke(@$callbacks['success'], array(curl_multi_getcontent($info['handle']), $curlOption)); } else { $errorNumber = curl_errno($info['handle']); $errorMessage = curl_error($info['handle']); // libcurl errors, try to parse it. if ($errorNumber === 0) { if (preg_match('/errno: (\\d+)/', $errorMessage, $matches)) { $errorNumber = (int) $matches[1]; $curlErrors = unserialize(FRAMEWORK_NET_CURL_ERRORS); if (isset($curlErrors[$errorNumber])) { $errorMessage = $curlErrors[$errorNumber]; } } } Utility::forceInvoke(@$callbacks['failure'], array($errorNumber, $errorMessage, $curlOption)); unset($errorNumber, $errorMessage); } // Always handler Utility::forceInvoke(@$callbacks['always'], array($curlOption)); if (isset($options[$requestIndex])) { curl_multi_add_handle($multiHandle, $options[$requestIndex++]['handle']); // Keep the loop alive. $active = TRUE; } curl_multi_remove_handle($multiHandle, $info['handle']); curl_close($info['handle']); unset($info, $callbacks, $curlOption, $options[$optionIndex], $optionIndex); } while ($queueLength > 0); } while ($status === CURLM_CALL_MULTI_PERFORM || $active); curl_multi_close($multiHandle); }
/** * Upsert function. * * @param $table Target table name. * @param $data Key-value pairs of field names and values. * * @returns True on update succeed, insertId on a row inserted, false on failure. */ public static function upsert($table, array $data, $update = null) { $fields = static::escapeField(array_keys($data), $table); $values = array_values($data); $query = sprintf('INSERT INTO %s (%s) VALUES (%s)', static::escapeField($table), implode(', ', $fields), implode(', ', array_fill(0, count($fields), '?'))); // append "ON DUPLICATE KEY UPDATE ..." $keys = static::getFields($table, 'PRI'); $fields = array_intersect($fields, static::escapeField($keys, $table)); if ($fields) { // selective update if ($update !== null) { $data = array_select($data, (array) $update); } foreach ($data as $field => $value) { $data["`{$field}` = ?"] = $value; unset($data[$field]); } // full dataset appended with non-key fields $values = array_merge($values, array_values(array_filter_keys($data, notIn($keys)))); $query .= ' ON DUPLICATE KEY UPDATE '; if ($data) { $query .= implode(', ', array_keys($data)); } else { // note: key1 = key1; We do not use INSERT IGNORE because it'll ignore other errors. $value = reset($fields); $query .= "{$value} = {$value}"; unset($value); } } unset($keys, $fields); $res = static::query($query, $values); unset($query, $values); if ($res !== false) { $res->closeCursor(); // Inserted, return the new ID. if ($res->rowCount() == 1) { // Note: mysql_insert_id() doesn't do UNSIGNED ZEROFILL! $res = (int) static::getConnection()->lastInsertId(); //$res = static::fetchField("SELECT MAX(ID) FROM `$table`;"); } else { $res = true; } } return $res; }
/** * Handles saving updated category information from the category editor * * @author Jonathan Davis * @since 1.0 * @return void **/ public function save($Category) { $Shopp = Shopp::object(); check_admin_referer('shopp-save-category'); if (!current_user_can('shopp_categories')) { wp_die(__('You do not have sufficient permissions to access this page.')); } shopp_set_formsettings(); // Save workflow setting if (empty($Category->meta)) { $Category->load_meta(); } if (isset($_POST['content'])) { $_POST['description'] = $_POST['content']; } $Category->name = $_POST['name']; $Category->description = $_POST['description']; $Category->parent = $_POST['parent']; $Category->prices = array(); // Variation price templates if (!empty($_POST['price']) && is_array($_POST['price'])) { foreach ($_POST['price'] as &$pricing) { $pricing['price'] = Shopp::floatval($pricing['price'], false); $pricing['saleprice'] = Shopp::floatval($pricing['saleprice'], false); $pricing['shipfee'] = Shopp::floatval($pricing['shipfee'], false); $pricing['dimensions'] = array_map(array('Shopp', 'floatval'), $pricing['dimensions']); } } $_POST['prices'] = isset($_POST['price']) ? $_POST['price'] : array(); if (empty($_POST['specs'])) { $Category->specs = array(); } /* @todo Move the rest of category meta inputs to [meta] inputs eventually */ if (isset($_POST['meta']) && isset($_POST['meta']['options'])) { // Moves the meta options input to 'options' index for compatibility $_POST['options'] = $_POST['meta']['options']; } if (empty($_POST['meta']['options']) || count($_POST['meta']['options']['v']) == 1 && !isset($_POST['meta']['options']['v'][1]['options'])) { $_POST['options'] = $Category->options = array(); $_POST['prices'] = $Category->prices = array(); } $metaprops = array('spectemplate', 'facetedmenus', 'variations', 'pricerange', 'priceranges', 'specs', 'options', 'prices'); $metadata = array_filter_keys($_POST, $metaprops); // Update existing entries $updates = array(); foreach ($Category->meta as $id => $MetaObject) { $name = $MetaObject->name; if (isset($metadata[$name])) { $MetaObject->value = stripslashes_deep($metadata[$name]); $updates[] = $name; } } // Create any new missing meta entries $new = array_diff(array_keys($metadata), $updates); // Determine new entries from the exsting updates foreach ($new as $name) { if (!isset($metadata[$name])) { continue; } $Meta = new MetaObject(); $Meta->name = $name; $Meta->value = stripslashes_deep($metadata[$name]); $Category->meta[] = $Meta; } $Category->save(); if (!empty($_POST['deleteImages'])) { $deletes = array(); if (strpos($_POST['deleteImages'], ",")) { $deletes = explode(',', $_POST['deleteImages']); } else { $deletes = array($_POST['deleteImages']); } $Category->delete_images($deletes); } if (!empty($_POST['images']) && is_array($_POST['images'])) { $Category->link_images($_POST['images']); $Category->save_imageorder($_POST['images']); if (!empty($_POST['imagedetails']) && is_array($_POST['imagedetails'])) { foreach ($_POST['imagedetails'] as $i => $data) { $Image = new CategoryImage($data['id']); $Image->title = $data['title']; $Image->alt = $data['alt']; $Image->save(); } } } do_action_ref_array('shopp_category_saved', array($Category)); $this->notice(Shopp::__('%s category saved.', '<strong>' . $Category->name . '</strong>')); }
/** * Because POST can be JSON, or other formats in the future, we cannot simply * use $_REQUEST. * * Another difference with $_REQUEST is this also counts $_COOKIE. */ public function param($name = null, $type = null) { /*! Note @ 23 Apr, 2015 * POST validation should be simple, just match it with some hash key stored in sessions. */ // TODO: Do form validation, take reference from form key of Magento. $result = $this->_param($type); if (is_array($result)) { // remove meta keys and sensitive values $result = array_filter_keys($result, funcAnd(notIn([ini_get('session.name')]), compose('not', startsWith($this->metaPrefix)))); } if ($name === null) { return $result; } else { $fx = prop($name); return $fx($result); } }
/** * */ public function testArrayFilterKeys() { $array = ['fii' => 3, 'faa' => 2, 'foo' => 1]; $this->assertEquals(array_filter_keys($array, ['faa']), ['faa' => 2]); }
function require_method($Method, $Target = false) { // A simple way to enforce usage of the intended HTTP method for a given page if (strcasecmp($_SERVER['REQUEST_METHOD'], $Method) === 0) { return; } error_log("Rejected non-{$Method} request for {$_SERVER['REQUEST_URI']}. \$_SERVER=" . unwrap(var_export(array_filter_keys($_SERVER, array("HTTP_REFERER", 'HTTP_USER_AGENT', 'HTTP_HOST', 'REQUEST_METHOD', 'REQUEST_URI', 'QUERY_STRING')), true))); redirect($Target); }