1
0

Initial g3 remote client implementation

This commit is contained in:
Tim Almdal 2009-12-12 09:39:18 -08:00
parent 4f1538d87b
commit 5676a82322
153 changed files with 26514 additions and 0 deletions

320
web_client/@install.php Normal file
View File

@ -0,0 +1,320 @@
<?php defined('SYSPATH') OR die('No direct access allowed. This file is automatically ran by index.php.'); ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Kohana Installation</title>
<style type="text/css">
body {
width: 42em;
margin: 0 auto;
font-family: sans-serif;
font-size: 90%;
}
#tests table {
border-collapse: collapse;
width: 100%;
}
#tests table th, #tests table td {
padding: 0.2em 0.4em;
text-align: left;
vertical-align: top;
}
#tests table th {
width: 12em;
font-weight: normal;
font-size: 1.2em;
}
#tests table tr:nth-child(odd) {
background: #eee;
}
#tests table td.pass {
color: #191;
}
#tests table td.fail {
color: #911;
}
#tests #results {
color: #fff;
}
#tests #results p {
padding: 0.8em 0.4em;
}
#tests #results p.pass {
background: #191;
}
#tests #results p.fail {
background: #911;
}
</style>
</head>
<body>
<h1>Environment Tests</h1>
<p>
The following tests have been run to determine if Kohana will work in your environment. If any of the tests have failed, consult the <a href="http://docs.kohanaphp.com/installation">documentation</a>
for more information on how to correct the problem.
</p>
<div id="tests">
<?php $failed = FALSE?>
<table cellspacing="0">
<tr>
<th>PHP Version</th>
<?php if (version_compare(PHP_VERSION, '5.2', '>=')): ?>
<td class="pass">
<?php echo PHP_VERSION?>
</td>
<?php else : $failed = TRUE?>
<td class="fail">
Kohana requires PHP 5.2 or newer, this version is <?php echo PHP_VERSION?>.
</td>
<?php endif?>
</tr>
<tr>
<th>System Directory</th>
<?php if (is_dir(SYSPATH)): ?>
<td class="pass">
<?php echo SYSPATH?>
</td>
<?php else : $failed = TRUE?>
<td class="fail">
The configured
<code>
system
</code>
directory does not exist or does not contain required files.
</td>
<?php endif?>
</tr>
<tr>
<th>Application Directory</th>
<?php if (is_dir(APPPATH) AND is_file(APPPATH.'config/config'.EXT) AND is_file(APPPATH.'Bootstrap'.EXT)): ?>
<td class="pass">
<?php echo APPPATH?>
</td>
<?php else : $failed = TRUE?>
<td class="fail">
The configured
<code>
application
</code>
directory does not exist or does not contain required files.
</td>
<?php endif?>
</tr>
<tr>
<th>Modules Directory</th>
<?php if (is_dir(MODPATH)): ?>
<td class="pass">
<?php echo MODPATH?>
</td>
<?php else : $failed = TRUE?>
<td class="fail">
The configured
<code>
modules
</code>
directory does not exist or does not contain required files.
</td>
<?php endif?>
</tr>
<tr>
<th>Logs Directory</th>
<?php if (is_dir(APPPATH.'logs') AND is_writable(APPPATH.'logs')): ?>
<td class="pass">
Pass
</td>
<?php else : $failed = TRUE?>
<td class="fail">
The default
<code>
logs
</code>
directory does not exist or is not writable. Depending on your log driver and config settings, this may not be a problem.
</td>
<?php endif?>
</tr>
<tr>
<th>Cache Directory</th>
<?php if (is_dir(APPPATH.'cache') AND is_writable(APPPATH.'cache')): ?>
<td class="pass">
Pass
</td>
<?php else : $failed = TRUE?>
<td class="fail">
The default
<code>
cache
</code>
directory does not exist or is not writable. Depending on your cache driver and config settings, this may not be a problem.
</td>
<?php endif?>
</tr>
<tr>
<th>PCRE UTF-8</th>
<?php if ( ! function_exists('preg_match')): $failed = TRUE?>
<td class="fail">
<a href="http://php.net/pcre">PCRE</a>
support is missing.
</td>
<?php elseif ( ! @preg_match('/^.$/u', 'ñ')): $failed = TRUE?>
<td class="fail">
<a href="http://php.net/pcre">PCRE</a>
has not been compiled with UTF-8 support.
</td>
<?php elseif ( ! @preg_match('/^\pL$/u', 'ñ')): $failed = TRUE?>
<td class="fail">
<a href="http://php.net/pcre">PCRE</a>
has not been compiled with Unicode property support.
</td>
<?php else : ?>
<td class="pass">
Pass
</td>
<?php endif?>
</tr>
<tr>
<th>Reflection Enabled</th>
<?php if (class_exists('ReflectionClass')): ?>
<td class="pass">
Pass
</td>
<?php else : $failed = TRUE?>
<td class="fail">
PHP <a href="http://www.php.net/reflection">reflection</a>
is either not loaded or not compiled in.
</td>
<?php endif?>
</tr>
<tr>
<th>Filters Enabled</th>
<?php if (function_exists('filter_list')): ?>
<td class="pass">
Pass
</td>
<?php else : $failed = TRUE?>
<td class="fail">
The <a href="http://www.php.net/filter">filter</a>
extension is either not loaded or not compiled in.
</td>
<?php endif?>
</tr>
<tr>
<th>Iconv Extension Loaded</th>
<?php if (extension_loaded('iconv')): ?>
<td class="pass">
Pass
</td>
<?php else : $failed = TRUE?>
<td class="fail">
The <a href="http://php.net/iconv">iconv</a>
extension is not loaded.
</td>
<?php endif?>
</tr>
<tr>
<th>SPL Enabled</th>
<?php if (function_exists('spl_autoload_register')): ?>
<td class="pass">
Pass
</td>
<?php else : $failed = TRUE?>
<td class="fail">
<a href="http://php.net/spl">SPL</a>
is not enabled.
</td>
<?php endif?>
</tr>
<tr>
<th>Multibyte String Enabled</th>
<?php if (extension_loaded('mbstring')): ?>
<td class="pass">Pass</td>
<?php else: $failed = TRUE; ?>
<td class="fail">The <a href="http://php.net/mbstring">mbstring</a>
extension is not loaded.</td>
<?php endif ?>
</tr>
<?php if (extension_loaded('mbstring')): ?>
<tr>
<th>Mbstring Not Overloaded</th>
<?php if (ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING): $failed = TRUE?>
<td class="fail">
The <a href="http://php.net/mbstring">mbstring</a>
extension is overloading PHP's native string functions.
</td>
<?php else : ?>
<td class="pass">
Pass
</td>
<?php endif?>
</tr>
<?php endif?>
<tr>
<th>XML support</th>
<?php if ( ! function_exists('utf8_encode')): $failed = TRUE?>
<td class="fail">
PHP is compiled without <a href="http://php.net/xml">XML</a>
support, thus lacking support for
<code>
utf8_encode()
</code>/
<code>
utf8_decode()
</code>.
</td>
<?php else : ?>
<td class="pass">
Pass
</td>
<?php endif?>
</tr>
<th>Timezone</th>
<?php try { new DateTimeZone(ini_get('date.timezone')); ?>
<td class="pass">Pass</td>
<?php } catch (Exception $e) { $failed = TRUE ?>
<td class="fail">
The current timezone, <code>'<?php echo ini_get('date.timezone') ?>'</code>, is not valid.
You must configure it in <code>php.ini</code> or <code>config/locale.php</code>.
</td>
<?php } ?>
</tr>
<tr>
<th>URI Determination</th>
<?php if (isset($_SERVER['SCRIPT_NAME']) AND (isset($_SERVER['PATH_INFO']) OR isset($_SERVER['ORIG_PATH_INFO']) OR isset($_SERVER['PHP_SELF']))): ?>
<td class="pass">
Pass
</td>
<?php else : $failed = TRUE?>
<td class="fail">
At least one of <code>$_SERVER['PATH_INFO']</code>, <code>$_SERVER['ORIG_PATH_INFO']</code>, or <code>$_SERVER['PHP_SELF']</code> must be available.
</td>
<?php endif?>
</tr>
</table>
<div id="results">
<?php if ($failed === TRUE): ?>
<p class="fail">
Kohana may not work correctly with your environment.
</p>
<?php else : ?>
<p class="pass">
Your environment passed all requirements. Remove or rename the
<code>
install<?php echo EXT?>
</code>
file now.
</p>
<?php endif?>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,30 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Kohana License</title>
</head>
<body>
<h2>Kohana License Agreement</h2>
<p>This license is a legal agreement between you and the Kohana Software Foundation for the use of Kohana Framework (the "Software"). By obtaining the Software you agree to comply with the terms and conditions of this license.</p>
<p>Copyright (c) 2007-2009 Kohana Team<br/>All rights reserved.</p>
<p>Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:</p>
<ul>
<li>Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.</li>
<li>Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.</li>
<li>Neither the name of the Kohana nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.</li>
</ul>
<p>THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</p>
<p><small>NOTE: This license is modeled after the BSD software license.</small></p>
</body>
</html>

View File

@ -0,0 +1,59 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Kohana process control file, loaded by the front controller.
*
* $Id: Bootstrap.php 4679 2009-11-10 01:45:52Z isaiah $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
// Kohana benchmarks are prefixed to prevent collisions
define('SYSTEM_BENCHMARK', 'system_benchmark');
// Load benchmarking support
require SYSPATH.'core/Benchmark'.EXT;
// Start total_execution
Benchmark::start(SYSTEM_BENCHMARK.'_total_execution');
// Start kohana_loading
Benchmark::start(SYSTEM_BENCHMARK.'_kohana_loading');
// Load core files
require SYSPATH.'core/Event'.EXT;
final class Event extends Event_Core {}
require SYSPATH.'core/Kohana'.EXT;
final class Kohana extends Kohana_Core {}
require SYSPATH.'core/Kohana_Exception'.EXT;
class Kohana_Exception extends Kohana_Exception_Core {}
require SYSPATH.'core/Kohana_Config'.EXT;
require SYSPATH.'libraries/drivers/Config'.EXT;
require SYSPATH.'libraries/drivers/Config/Array'.EXT;
final class Kohana_Config extends Kohana_Config_Core {}
// Prepare the environment
Kohana::setup();
// End kohana_loading
Benchmark::stop(SYSTEM_BENCHMARK.'_kohana_loading');
// Start system_initialization
Benchmark::start(SYSTEM_BENCHMARK.'_system_initialization');
// Prepare the system
Event::run('system.ready');
// Determine routing
Event::run('system.routing');
// End system_initialization
Benchmark::stop(SYSTEM_BENCHMARK.'_system_initialization');
// Make the magic happen!
Event::run('system.execute');

View File

@ -0,0 +1 @@
*

View File

@ -0,0 +1,118 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Base path of the web site. If this includes a domain, eg: localhost/kohana/
* then a full URL will be used, eg: http://localhost/kohana/. If it only includes
* the path, and a site_protocol is specified, the domain will be auto-detected.
*/
$config['site_domain'] = '/g3_client/';
/**
* Force a default protocol to be used by the site. If no site_protocol is
* specified, then the current protocol is used, or when possible, only an
* absolute path (with no protocol/domain) is used.
*/
$config['site_protocol'] = '';
/**
* Name of the front controller for this application. Default: index.php
*
* This can be removed by using URL rewriting.
*/
$config['index_page'] = 'index.php';
/**
* Fake file extension that will be added to all generated URLs. Example: .html
*/
$config['url_suffix'] = '';
/**
* Length of time of the internal cache in seconds. 0 or FALSE means no caching.
* The internal cache stores file paths and config entries across requests and
* can give significant speed improvements at the expense of delayed updating.
*/
$config['internal_cache'] = FALSE;
/**
* Internal cache directory.
*/
$config['internal_cache_path'] = APPPATH.'cache/';
/**
* Enable internal cache encryption - speed/processing loss
* is neglible when this is turned on. Can be turned off
* if application directory is not in the webroot.
*/
$config['internal_cache_encrypt'] = TRUE;
/**
* Encryption key for the internal cache, only used
* if internal_cache_encrypt is TRUE.
*
* Make sure you specify your own key here!
*
* The cache is deleted when/if the key changes.
*/
$config['internal_cache_key'] = 'g3_client';
/**
* Enable or disable gzip output compression. This can dramatically decrease
* server bandwidth usage, at the cost of slightly higher CPU usage. Set to
* the compression level (1-9) that you want to use, or FALSE to disable.
*
* Do not enable this option if you are using output compression in php.ini!
*/
$config['output_compression'] = FALSE;
/**
* Enable or disable global XSS filtering of GET, POST, and SERVER data. This
* option also accepts a string to specify a specific XSS filtering tool.
*/
$config['global_xss_filtering'] = FALSE;
/**
* Enable or disable hooks.
*/
$config['enable_hooks'] = FALSE;
/**
* Enable or disable displaying of Kohana error pages. This will not affect
* logging. Turning this off will disable ALL error pages.
*/
$config['display_errors'] = TRUE;
/**
* Enable or disable statistics in the final output. Stats are replaced via
* specific strings, such as {execution_time}.
*
* @see http://docs.kohanaphp.com/general/configuration
*/
$config['render_stats'] = TRUE;
/**
* Filename prefixed used to determine extensions. For example, an
* extension to the Controller class would be named MY_Controller.php.
*/
$config['extension_prefix'] = 'MY_';
/**
* An optional list of Config Drivers to use, they "fallback" to the one below them if they
* dont work so the first driver is tried then so on until it hits the built in "array" driver and fails
*/
$config['config_drivers'] = array();
/**
* Additional resource paths, or "modules". Each path can either be absolute
* or relative to the docroot. Modules can include any resource that can exist
* in your application directory, configuration files, controllers, views, etc.
*/
$config['modules'] = array
(
// MODPATH.'auth', // Authentication
// MODPATH.'forge', // Form generation
// MODPATH.'kodoc', // Self-generating documentation
// MODPATH.'media', // Media caching and compression
// MODPATH.'gmaps', // Google Maps integration
// MODPATH.'archive', // Archive utility
// MODPATH.'payment', // Online payments
// MODPATH.'unit_test', // Unit testing
// MODPATH.'object_db', // New OOP Database library (testing only!)
);

View File

@ -0,0 +1,5 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Base path of the gallery3 web site
*/
$config["gallery3_site"] = "http://sandbox.timalmdal.com/gallery3/index.php/rest";

View File

@ -0,0 +1,7 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* @package Core
*
* Sets the default route to "welcome"
*/
$config['_default'] = 'g3_client';

View File

@ -0,0 +1,99 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Gallery - a web based photo album viewer and editor
* Copyright (C) 2000-2009 Bharat Mediratta
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class G3_Client_Controller extends Template_Controller {
// Set the name of the template to use
public $template = 'g3_template.html';
public function index() {
$this->template->title = 'G3 Web Client';
if (Session::instance()->get("g3_client_access_token")) {
$resource = G3Remote::instance()->get_resource("gallery");
$this->template->album_tree = $this->_get_album_tree($resource);
$this->template->detail = $this->_get_detail($resource);
} else {
$this->template->content = new View('login.html');
$this->template->content->errors = $this->template->content->form =
array("user" => "", "password" => "");
}
}
public function login() {
$form = $errors = array("user" => "", "password" => "");
$post = new Validation($_POST);
$post->add_rules("user", "required");
$post->add_rules("password", "required");
if ($valid =$post->validate()) {
try {
$token = G3Remote::instance()->get_access_token($post["user"], $post["password"]);
Session::instance()->set("g3_client_access_token", $token);
$resource = G3Remote::instance()->get_resource("gallery");
$content = array(
"album_tree" => $this->_get_album_tree($resource),
"detail" => $this->_get_detail($resource));
} catch (Exception $e) {
Kohana_Log::add("error", Kohana_Exception::text($e));
$valid = false;
}
}
if (!$valid) {
$content = new View('login.html');
$content->form = arr::overwrite($form, $post->as_array());
$content->errors = arr::overwrite($errors, $post->errors());
}
$this->auto_render = false;
print json_encode(array("status" => $valid ? "ok" : "error", "content" => $content));
}
public function albums() {
$path = $this->input->get("path");
$resource = G3Remote::instance()->get_resource("gallery/$path", "album");
$this->auto_render = false;
print $this->_get_album_tree($resource);
}
public function detail() {
$path = $this->input->get("path");
$resource = G3Remote::instance()->get_resource("gallery/$path");
$this->auto_render = false;
print $this->_get_detail($resource);
}
private function _get_album_tree($resource) {
$v = new View("tree_part.html");
$v->element = (object)array("title" => $resource->title, "path" => $resource->path);
$v->element->children = array();
foreach ($resource->children as $child) {
if ($child->type != "album") {
continue;
}
$v->element->children[] = $child;
}
return $v;
}
private function _get_detail($resource) {
$v = new View("{$resource->type}_detail.html");
$v->resource = $resource;
return $v;
}
} // End G3 Client Controller

View File

@ -0,0 +1,252 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Gallery - a web based photo album viewer and editor
* Copyright (C) 2000-2009 Bharat Mediratta
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
class url_connection {
static function post($url, $post_data_array, $extra_headers=array()) {
$_data_raw = self::_encode_data($post_data_array, $extra_headers);
$extra_headers['Content-Type'] = 'application/x-www-form-urlencoded';
$extra_headers['Content-Length'] = strlen($_data_raw);
/* Read the web page into a buffer */
list ($response_status, $response_headers, $response_body) =
self::do_request($url, 'POST', $extra_headers, $post_data_raw);
return array($response_body, $response_status, $response_headers);
}
static function get($url, $_data_array=array(), $extra_headers=array()) {
$_data_raw = self::_encode_data($_data_array, $extra_headers);
/* Read the web page into a buffer */
list ($response_status, $response_headers, $response_body) =
self::do_request("{$url}?$_data_raw", "GET", $extra_headers);
return array($response_body, $response_status, $response_headers);
}
static function success($response_status) {
return preg_match("/^HTTP\/\d+\.\d+\s2\d{2}(\s|$)/", trim($response_status));
}
/**
* Encode the data. For each key/value pair, urlencode both the key and the value and then
* concatenate together. As per the specification, each key/value pair is separated with an
* ampersand (&)
* @param array $data_array the key/value data
* @param array $extra_headers extra headers to pass to the server
* @return string the encoded post data
*/
private static function _encode_data($_data_array, &$extra_headers) {
$_data_raw = '';
foreach ($_data_array as $key => $value) {
if (!empty($_data_raw)) {
$_data_raw .= '&';
}
$_data_raw .= urlencode($key) . '=' . urlencode($value);
}
return $_data_raw;
}
/**
* A single request, without following redirects
*
* @todo: Handle redirects? If so, only for GET (i.e. not for POST), and use G2's
* WebHelper_simple::_parseLocation logic.
*/
static function do_request($url, $method='GET', $headers=array(), $body='') {
/* Convert illegal characters */
$url = str_replace(' ', '%20', $url);
$url_components = self::_parse_url_for_fsockopen($url);
$handle = fsockopen(
$url_components['fsockhost'], $url_components['port'], $errno, $errstr, 5);
if (empty($handle)) {
// log "Error $errno: '$errstr' requesting $url";
return array(null, null, null);
}
$header_lines = array('Host: ' . $url_components['host']);
foreach ($headers as $key => $value) {
$header_lines[] = $key . ': ' . $value;
}
$success = fwrite($handle, sprintf("%s %s HTTP/1.0\r\n%s\r\n\r\n%s",
$method,
$url_components['uri'],
implode("\r\n", $header_lines),
$body));
if (!$success) {
// Zero bytes written or false was returned
// log "fwrite failed in requestWebPage($url)" . ($success === false ? ' - false' : ''
return array(null, null, null);
}
fflush($handle);
/*
* Read the status line. fgets stops after newlines. The first line is the protocol
* version followed by a numeric status code and its associated textual phrase.
*/
$response_status = trim(fgets($handle, 4096));
if (empty($response_status)) {
// 'Empty http response code, maybe timeout'
return array(null, null, null);
}
/* Read the headers */
$response_headers = array();
while (!feof($handle)) {
$line = trim(fgets($handle, 4096));
if (empty($line)) {
break;
}
/* Normalize the line endings */
$line = str_replace("\r", '', $line);
list ($key, $value) = explode(':', $line, 2);
if (isset($response_headers[$key])) {
if (!is_array($response_headers[$key])) {
$response_headers[$key] = array($response_headers[$key]);
}
$response_headers[$key][] = trim($value);
} else {
$response_headers[$key] = trim($value);
}
}
/* Read the body */
$response_body = '';
while (!feof($handle)) {
$response_body .= fread($handle, 4096);
}
fclose($handle);
return array($response_status, $response_headers, $response_body);
}
/**
* Prepare for fsockopen call.
* @param string $url
* @return array url components
* @access private
*/
private static function _parse_url_for_fsockopen($url) {
$url_components = parse_url($url);
if (strtolower($url_components['scheme']) == 'https') {
$url_components['fsockhost'] = 'ssl://' . $url_components['host'];
$default_port = 443;
} else {
$url_components['fsockhost'] = $url_components['host'];
$default_port = 80;
}
if (empty($url_components['port'])) {
$url_components['port'] = $default_port;
}
if (empty($url_components['path'])) {
$url_components['path'] = '/';
}
$uri = $url_components['path']
. (empty($url_components['query']) ? '' : '?' . $url_components['query']);
/* Unescape ampersands, since if the url comes from form input it will be escaped */
$url_components['uri'] = str_replace('&amp;', '&', $uri);
return $url_components;
}
}
// This class does not depend on any Kohana services so that it can be used in non-Kohana
// applications.
class G3Remote {
protected static $_instance;
protected $_config;
private $_resources;
private $_access_token;
private $_identity;
public static function instance($access_token=null) {
if (!isset(G3Remote::$_instance)) {
G3Remote::$_instance = new G3Remote($access_token);
}
return G3Remote::$_instance;
}
/**
* Constructs a new G3Remote object
*
* @param array Database config array
* @return G3Remote
*/
protected function __construct($access_token) {
// Store the config locally
$this->_config = Kohana::config("g3_remote");
$this->_access_token = $access_token;
}
public function get_access_token($user, $password) {
$identity = md5("$user/$password");
if (empty($this->_identity) || $this->_identity != $identity) {
$request = "{$this->_config["gallery3_site"]}/access_key";
list ($response_body, $response_status, $response_headers) =
url_connection::get($request, array("user" => $user, "password" => $password));
if (url_connection::success($response_status)) {
$response = json_decode($response_body);
if ($response->status == "OK") {
$this->_access_token = $response->token;
$this->_identity = $identity;
} else {
throw new Exception("Remote host failure: {$response->message}");
}
} else {
throw new Exception("Remote host failure: $response_status");
}
}
return $this->_access_token;
}
public function get_resource($path, $filter=false, $offset=false, $limit=false) {
$request = "{$this->_config["gallery3_site"]}/$path";
$params = array();
if ($filter) {
$param["filter"] = $filter;
}
if ($offset) {
$param["offset"] = $offset;
}
if ($limit) {
$param["limit"] = $limit;
}
list ($response_body, $response_status, $response_headers) =
url_connection::get($request, $params);
if (url_connection::success($response_status)) {
$response = json_decode($response_body);
if ($response->status != "OK") {
throw new Exception("Remote host failure: {$response->message}");
}
} else {
throw new Exception("Remote host failure: $response_status");
}
return $response->resource;
}
}

View File

@ -0,0 +1 @@
*

View File

@ -0,0 +1,15 @@
<?php defined("SYSPATH") or die("No direct script access.") ?>
<ul id="thumb-grid" class="ui-helper-clearfix">
<? foreach ($resource->children as $child): ?>
<li class="thumb-grid-cell" ref="<?= $child->path ?>">
<a href="g3_client/show/<?= $child->path ?>">
<? if ($child->has_thumb): ?>
<img src="<?= $child->thumb_url ?>" title="<?= $child->title ?>" />
<? else: ?>
<span><?= $child->title ?></span>
<? endif ?>
</a>
</li>
<? endforeach ?>
</ul>

View File

@ -0,0 +1,49 @@
<?php defined('SYSPATH') OR die('No direct access allowed.'); ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title><?= html::chars(__($title)) ?></title>
<?= html::stylesheet("css/reset-fonts-grids.css") ?>
<?= html::stylesheet("css/g3_client.css") ?>
<?= html::stylesheet("css/jquery-ui.css") ?>
<!--[if lt IE 8]>
<link rel="stylesheet" type="text/css" href="<?= url::file("css/fix-ie.css") ?>"
media="screen,print,projection" />
<![endif]-->
<style type="text/css">
.copyright { font-size: 0.9em; text-transform: uppercase; color: #557d10; }
</style>
<?= html::script("js/jquery.js") ?>
<?= html::script("js/jquery.form.js") ?>
<?= html::script("js/jquery-ui.js") ?>
<?= html::script("js/g3_client.js") ?>
<script type="text/javascript">
$(document).ready(function () {
$("#body div").gallery3_client();
});
</script>
</head>
<body>
<div id="doc4" class="yui-t5">
<div id="header" class="ui-helper-clearfix">
<div>&nbsp;</div>
</div>
<div id="body">
<div id="left">
<ul id="album_tree"><?= $album_tree ?></ul>
</div>
<div id="center">
<?= $detail ?>
</div>
</div>
<div id="footer" class="ui-helper-clearfix">
<p class="copyright">
<?= __('Rendered in {execution_time} seconds, using {memory_usage} of memory')?><br />
Copyright ©20092010 Gallery Team
</p>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,27 @@
<?php defined("SYSPATH") or die("No direct script access.") ?>
<ul>
<li id="g-login-form">
<?= form::open("g3_client/login") ?>
<fieldset>
<legend>Please provide your userid and password for the remote system</legend>
<ul>
<li>
<?= form::label("user", "User Id:") ?><br/>
<?= form::input("user", $form["user"]) ?>
<?= empty($errors["user"]) ? "" : "<span class=\"error\">{$errors["user"]}</span>" ?>
</li>
<li>
<?= form::label("password", "Password") ?><br/>
<?= form::password("password", $form["password"]) ?>
<?= empty($errors["password"]) ? "" : "<span class=\"error\">{$errors["password"]}</span>" ?>
</li>
<li>
<?= form::submit("submit", "Login") ?>
<?= form::input(array('type'=>'reset','name'=>'reset'), "Reset") ?>
</li>
</ul>
</fieldset>
</form>
</li>
</ul>

View File

@ -0,0 +1,14 @@
<?php defined("SYSPATH") or die("No direct script access.") ?>
<li class="ui-icon-left" ref="<?= $element->path ?>">
<span class="<?= count($element->children) > 0 ? "ui-icon ui-icon-minus" : "ui-icon-none" ?>" >&nbsp;</span>
<span class="tree-title"><?= $element->title ?></span>
<ul class="ui-helper-clearfix tree-chidren">
<? foreach ($element->children as $child): ?>
<li ref="<?= $child->path ?>" class="ui-icon-left">
<span class="<?= $child->has_children ? "ui-icon ui-icon-plus" : "ui-icon-none" ?>">&nbsp;</span>
<span class="tree-title"><?= $child->title ?></span>
</li>
<? endforeach ?>
</ul>
</li>

View File

@ -0,0 +1,15 @@
<?php defined('SYSPATH') OR die('No direct access allowed.'); ?>
<div class="box">
<p><?php echo __('This is the default Kohana index page. You may also access this page as')?> <code><?php echo html::anchor('welcome/index', 'welcome/index') ?></code>.</p>
<p>
<?php echo __('To change what gets displayed for this page, edit')?> <code>application/controllers/welcome.php</code>.<br />
<?php echo __('To change this text, edit')?> <code>application/views/welcome_content.php</code>.
</p>
</div>
<ul>
<?php foreach ($links as $title => $url): ?>
<li><?php echo ($title === 'License') ? html::file_anchor($url, html::chars(__($title))) : html::anchor($url, html::chars(__($title))) ?></li>
<?php endforeach ?>
</ul>

29
web_client/css/fix-ie.css Normal file
View File

@ -0,0 +1,29 @@
/**
* Fix display in IE 6, 7
*/
#g-banner {
z-index: 2;
}
input.submit {
clear: none !important;
display: inline !important;
}
#g-add-tag-form input.textbox {
width: 110px;
}
#g-dialog .g-cancel {
display: inline-block !important;
float: none !important;
}
.g-paginator .g-text-right {
width: 29%;
}
.g-paginator .ui-icon-right {
width: 60px;
}

View File

@ -0,0 +1,118 @@
#header {
background-color: #E8E8E8;
left: 0px;
min-height: 90px;
padding: 0 20px;
position: fixed;
right: 0px;
height: 90px;
}
#header div {
background-image: url(g3_web.png);
background-repeat: no-repeat;
height: 90px;
}
#body {
background-color: #E8E8E8;
bottom: 40px;
left: 0px;
position: fixed;
right: 0px;
top: 90px;
}
#body #content {
background-color: #FFFFFF;
border: 1px solid #CCCCCC;
padding: 10px 20px;
height: 100%;
}
form li {
padding-top: .4em;
}
form legend {
font-size: 1.2em;
font-weight: bold;
}
span.error {
color: #FF0000;
}
#footer {
background-color: #E8E8E8;
bottom: 0px;
left: 0px;
min-height: 40px;
padding: 10px 20px;
position: fixed;
right: 0px;
}
.copyright {
font-size: 0.9em;
text-transform: uppercase;
color: #557d10;
}
#body #left {
background-color: #FFFFFF;
border: 2px inset;
bottom: 20px;
left: 20px;
margin: 0;
padding: 5px;
position: absolute;
top: 11px;
width: 191px;
}
#body #left #album_tree {
height: 100%;
overflow: auto;
font-size: 1.1em;
}
#body #left #album_tree ul li {
padding: 0 0 .2em 1.2em;
}
#body #center {
background-color: #FFFFFF;
border: 2px inset;
bottom: 20px;
left: 225px;
overflow: auto;
padding: 5px;
position: absolute;
right: 20px;
top: 11px;
}
.tree-title {
cursor: pointer;
}
#body #center .thumb-grid-cell {
float: left;
margin-right: 10px;
}
.ui-icon-left .ui-icon {
float: left;
margin-right: 0.2em;
}
.ui-icon-left .ui-icon-none {
float: left;
padding-left: 15px;
}
.ui-selected {
background-color: #E8E8E8;
color: #FF9933;
}

BIN
web_client/css/g3_web.pdn Normal file

Binary file not shown.

BIN
web_client/css/g3_web.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

406
web_client/css/jquery-ui.css vendored Normal file
View File

@ -0,0 +1,406 @@
/*
* jQuery UI CSS Framework
* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
*/
/* Layout helpers
----------------------------------*/
.ui-helper-hidden { display: none; }
.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
.ui-helper-clearfix { display: inline-block; }
/* required comment for clearfix to work in Opera \*/
* html .ui-helper-clearfix { height:1%; }
.ui-helper-clearfix { display:block; }
/* end clearfix */
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
/* Interaction Cues
----------------------------------*/
.ui-state-disabled { cursor: default !important; }
/* Icons
----------------------------------*/
/* states and images */
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
/* Misc visuals
----------------------------------*/
/* Overlays */
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
/*
* jQuery UI CSS Framework
* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS,%20Tahoma,%20Verdana,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=03_highlight_soft.png&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=02_glass.png&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=08_diagonals_thick.png&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px
*/
/* Component containers
----------------------------------*/
.ui-widget { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1.1em; }
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1em; }
.ui-widget-content { border: 1px solid #dddddd; background: #eeeeee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; color: #333333; }
.ui-widget-content a { color: #333333; }
.ui-widget-header { border: 1px solid #e78f08; background: #f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
.ui-widget-header a { color: #ffffff; }
/* Interaction states
----------------------------------*/
.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #cccccc; background: #f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1c94c4; outline: none; }
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #1c94c4; text-decoration: none; outline: none; }
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #fbcb09; background: #fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #c77405; outline: none; }
.ui-state-hover a, .ui-state-hover a:hover { color: #c77405; text-decoration: none; outline: none; }
.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #fbd850; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #eb8f00; outline: none; }
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #eb8f00; outline: none; text-decoration: none; }
/* Interaction Cues
----------------------------------*/
.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fed22f; background: #ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x; color: #363636; }
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636; }
.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat; color: #ffffff; }
.ui-state-error a, .ui-widget-content .ui-state-error a { color: #ffffff; }
.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #ffffff; }
.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; }
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
/* Icons
----------------------------------*/
/* states and images */
.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
.ui-widget-header .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
.ui-state-default .ui-icon { background-image: url(images/ui-icons_ef8c08_256x240.png); }
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }
.ui-state-active .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }
.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_228ef1_256x240.png); }
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffd27a_256x240.png); }
/* positioning */
.ui-icon-carat-1-n { background-position: 0 0; }
.ui-icon-carat-1-ne { background-position: -16px 0; }
.ui-icon-carat-1-e { background-position: -32px 0; }
.ui-icon-carat-1-se { background-position: -48px 0; }
.ui-icon-carat-1-s { background-position: -64px 0; }
.ui-icon-carat-1-sw { background-position: -80px 0; }
.ui-icon-carat-1-w { background-position: -96px 0; }
.ui-icon-carat-1-nw { background-position: -112px 0; }
.ui-icon-carat-2-n-s { background-position: -128px 0; }
.ui-icon-carat-2-e-w { background-position: -144px 0; }
.ui-icon-triangle-1-n { background-position: 0 -16px; }
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
.ui-icon-triangle-1-e { background-position: -32px -16px; }
.ui-icon-triangle-1-se { background-position: -48px -16px; }
.ui-icon-triangle-1-s { background-position: -64px -16px; }
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
.ui-icon-triangle-1-w { background-position: -96px -16px; }
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
.ui-icon-arrow-1-n { background-position: 0 -32px; }
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
.ui-icon-arrow-1-e { background-position: -32px -32px; }
.ui-icon-arrow-1-se { background-position: -48px -32px; }
.ui-icon-arrow-1-s { background-position: -64px -32px; }
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
.ui-icon-arrow-1-w { background-position: -96px -32px; }
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
.ui-icon-arrow-4 { background-position: 0 -80px; }
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
.ui-icon-extlink { background-position: -32px -80px; }
.ui-icon-newwin { background-position: -48px -80px; }
.ui-icon-refresh { background-position: -64px -80px; }
.ui-icon-shuffle { background-position: -80px -80px; }
.ui-icon-transfer-e-w { background-position: -96px -80px; }
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
.ui-icon-folder-collapsed { background-position: 0 -96px; }
.ui-icon-folder-open { background-position: -16px -96px; }
.ui-icon-document { background-position: -32px -96px; }
.ui-icon-document-b { background-position: -48px -96px; }
.ui-icon-note { background-position: -64px -96px; }
.ui-icon-mail-closed { background-position: -80px -96px; }
.ui-icon-mail-open { background-position: -96px -96px; }
.ui-icon-suitcase { background-position: -112px -96px; }
.ui-icon-comment { background-position: -128px -96px; }
.ui-icon-person { background-position: -144px -96px; }
.ui-icon-print { background-position: -160px -96px; }
.ui-icon-trash { background-position: -176px -96px; }
.ui-icon-locked { background-position: -192px -96px; }
.ui-icon-unlocked { background-position: -208px -96px; }
.ui-icon-bookmark { background-position: -224px -96px; }
.ui-icon-tag { background-position: -240px -96px; }
.ui-icon-home { background-position: 0 -112px; }
.ui-icon-flag { background-position: -16px -112px; }
.ui-icon-calendar { background-position: -32px -112px; }
.ui-icon-cart { background-position: -48px -112px; }
.ui-icon-pencil { background-position: -64px -112px; }
.ui-icon-clock { background-position: -80px -112px; }
.ui-icon-disk { background-position: -96px -112px; }
.ui-icon-calculator { background-position: -112px -112px; }
.ui-icon-zoomin { background-position: -128px -112px; }
.ui-icon-zoomout { background-position: -144px -112px; }
.ui-icon-search { background-position: -160px -112px; }
.ui-icon-wrench { background-position: -176px -112px; }
.ui-icon-gear { background-position: -192px -112px; }
.ui-icon-heart { background-position: -208px -112px; }
.ui-icon-star { background-position: -224px -112px; }
.ui-icon-link { background-position: -240px -112px; }
.ui-icon-cancel { background-position: 0 -128px; }
.ui-icon-plus { background-position: -16px -128px; }
.ui-icon-plusthick { background-position: -32px -128px; }
.ui-icon-minus { background-position: -48px -128px; }
.ui-icon-minusthick { background-position: -64px -128px; }
.ui-icon-close { background-position: -80px -128px; }
.ui-icon-closethick { background-position: -96px -128px; }
.ui-icon-key { background-position: -112px -128px; }
.ui-icon-lightbulb { background-position: -128px -128px; }
.ui-icon-scissors { background-position: -144px -128px; }
.ui-icon-clipboard { background-position: -160px -128px; }
.ui-icon-copy { background-position: -176px -128px; }
.ui-icon-contact { background-position: -192px -128px; }
.ui-icon-image { background-position: -208px -128px; }
.ui-icon-video { background-position: -224px -128px; }
.ui-icon-script { background-position: -240px -128px; }
.ui-icon-alert { background-position: 0 -144px; }
.ui-icon-info { background-position: -16px -144px; }
.ui-icon-notice { background-position: -32px -144px; }
.ui-icon-help { background-position: -48px -144px; }
.ui-icon-check { background-position: -64px -144px; }
.ui-icon-bullet { background-position: -80px -144px; }
.ui-icon-radio-off { background-position: -96px -144px; }
.ui-icon-radio-on { background-position: -112px -144px; }
.ui-icon-pin-w { background-position: -128px -144px; }
.ui-icon-pin-s { background-position: -144px -144px; }
.ui-icon-play { background-position: 0 -160px; }
.ui-icon-pause { background-position: -16px -160px; }
.ui-icon-seek-next { background-position: -32px -160px; }
.ui-icon-seek-prev { background-position: -48px -160px; }
.ui-icon-seek-end { background-position: -64px -160px; }
.ui-icon-seek-first { background-position: -80px -160px; }
.ui-icon-stop { background-position: -96px -160px; }
.ui-icon-eject { background-position: -112px -160px; }
.ui-icon-volume-off { background-position: -128px -160px; }
.ui-icon-volume-on { background-position: -144px -160px; }
.ui-icon-power { background-position: 0 -176px; }
.ui-icon-signal-diag { background-position: -16px -176px; }
.ui-icon-signal { background-position: -32px -176px; }
.ui-icon-battery-0 { background-position: -48px -176px; }
.ui-icon-battery-1 { background-position: -64px -176px; }
.ui-icon-battery-2 { background-position: -80px -176px; }
.ui-icon-battery-3 { background-position: -96px -176px; }
.ui-icon-circle-plus { background-position: 0 -192px; }
.ui-icon-circle-minus { background-position: -16px -192px; }
.ui-icon-circle-close { background-position: -32px -192px; }
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
.ui-icon-circle-zoomin { background-position: -176px -192px; }
.ui-icon-circle-zoomout { background-position: -192px -192px; }
.ui-icon-circle-check { background-position: -208px -192px; }
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
.ui-icon-circlesmall-close { background-position: -32px -208px; }
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
.ui-icon-squaresmall-close { background-position: -80px -208px; }
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
/* Misc visuals
----------------------------------*/
/* Corner radius */
.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; }
.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; }
.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; }
.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; }
.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
.ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; }
.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; }
.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; }
/* Overlays */
.ui-widget-overlay { background: #666666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat; opacity: .50;filter:Alpha(Opacity=50); }
.ui-widget-shadow { margin: -5px 0 0 -5px; padding: 5px; background: #000000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 5px; -webkit-border-radius: 5px; }/* Accordion
----------------------------------*/
.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
.ui-accordion .ui-accordion-li-fix { display: inline; }
.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 2.2em; }
.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; }
.ui-accordion .ui-accordion-content-active { display: block; }/* Datepicker
----------------------------------*/
.ui-datepicker { width: 17em; padding: .2em .2em 0; }
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
.ui-datepicker .ui-datepicker-prev { left:2px; }
.ui-datepicker .ui-datepicker-next { right:2px; }
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
.ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; }
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
.ui-datepicker select.ui-datepicker-month,
.ui-datepicker select.ui-datepicker-year { width: 49%;}
.ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; }
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
.ui-datepicker td { border: 0; padding: 1px; }
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
/* with multiple calendars */
.ui-datepicker.ui-datepicker-multi { width:auto; }
.ui-datepicker-multi .ui-datepicker-group { float:left; }
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
.ui-datepicker-row-break { clear:both; width:100%; }
/* RTL support */
.ui-datepicker-rtl { direction: rtl; }
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
.ui-datepicker-cover {
display: none; /*sorry for IE5*/
display/**/: block; /*sorry for IE5*/
position: absolute; /*must have*/
z-index: -1; /*must have*/
filter: mask(); /*must have*/
top: -4px; /*must have*/
left: -4px; /*must have*/
width: 200px; /*must have*/
height: 200px; /*must have*/
}/* Dialog
----------------------------------*/
.ui-dialog { position: relative; padding: .2em; width: 300px; }
.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative; }
.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; }
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
.ui-draggable .ui-dialog-titlebar { cursor: move; }
/* Progressbar
----------------------------------*/
.ui-progressbar { height:2em; text-align: left; }
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/* Resizable
----------------------------------*/
.ui-resizable { position: relative;}
.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; }
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; }
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; }
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; }
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Slider
----------------------------------*/
.ui-slider { position: relative; text-align: left; }
.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; }
.ui-slider-horizontal { height: .8em; }
.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
.ui-slider-horizontal .ui-slider-range-max { right: 0; }
.ui-slider-vertical { width: .8em; height: 100px; }
.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
.ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs
----------------------------------*/
.ui-tabs { padding: .2em; zoom: 1; }
.ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; }
.ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; }
.ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
.ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; }
.ui-tabs .ui-tabs-hide { display: none !important; }

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,19 @@
# Turn on URL rewriting
RewriteEngine On
# Installation directory
RewriteBase /kohana/
# Protect application and system files from being viewed
# This is only necessary when these files are inside the webserver document root
RewriteRule ^(application|modules|system) - [R=404,L]
# Allow any files or directories that exist to be displayed directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Rewrite all other URLs to index.php/URL
RewriteRule .* index.php/$0 [PT,L]
# Alternativly, if the rewrite rule above does not work try this instead:
#RewriteRule .* index.php?kohana_uri=$0 [PT,QSA,L]

107
web_client/index.php Normal file
View File

@ -0,0 +1,107 @@
<?php
/**
* This file acts as the "front controller" to your application. You can
* configure your application, modules, and system directories here.
* PHP error_reporting level may also be changed.
*
* @see http://kohanaphp.com
*/
/**
* Define the website environment status. When this flag is set to TRUE, some
* module demonstration controllers will result in 404 errors. For more information
* about this option, read the documentation about deploying Kohana.
*
* @see http://docs.kohanaphp.com/installation/deployment
*/
define('IN_PRODUCTION', FALSE);
/**
* Website application directory. This directory should contain your application
* configuration, controllers, models, views, and other resources.
*
* This path can be absolute or relative to this file.
*/
$kohana_application = 'application';
/**
* Kohana modules directory. This directory should contain all the modules used
* by your application. Modules are enabled and disabled by the application
* configuration file.
*
* This path can be absolute or relative to this file.
*/
$kohana_modules = 'modules';
/**
* Kohana system directory. This directory should contain the core/ directory,
* and the resources you included in your download of Kohana.
*
* This path can be absolute or relative to this file.
*/
$kohana_system = 'system';
/**
* Test to make sure that Kohana is running on PHP 5.2 or newer. Once you are
* sure that your environment is compatible with Kohana, you can comment this
* line out. When running an application on a new server, uncomment this line
* to check the PHP version quickly.
*/
version_compare(PHP_VERSION, '5.2', '<') and exit('Kohana requires PHP 5.2 or newer.');
/**
* Set the error reporting level. Unless you have a special need, E_ALL is a
* good level for error reporting.
*/
error_reporting(E_ALL & ~E_STRICT);
/**
* Turning off display_errors will effectively disable Kohana error display
* and logging. You can turn off Kohana errors in application/config/config.php
*/
ini_set('display_errors', TRUE);
/**
* If you rename all of your .php files to a different extension, set the new
* extension here. This option can left to .php, even if this file has a
* different extension.
*/
define('EXT', '.php');
//
// DO NOT EDIT BELOW THIS LINE, UNLESS YOU FULLY UNDERSTAND THE IMPLICATIONS.
// ----------------------------------------------------------------------------
// $Id: index.php 4587 2009-09-10 16:45:21Z isaiah $
//
$kohana_pathinfo = pathinfo(__FILE__);
// Define the front controller name and docroot
define('DOCROOT', $kohana_pathinfo['dirname'].DIRECTORY_SEPARATOR);
define('KOHANA', $kohana_pathinfo['basename']);
// If the front controller is a symlink, change to the real docroot
is_link(KOHANA) and chdir(dirname(realpath(__FILE__)));
// If kohana folders are relative paths, make them absolute.
$kohana_application = file_exists($kohana_application) ? $kohana_application : DOCROOT.$kohana_application;
$kohana_modules = file_exists($kohana_modules) ? $kohana_modules : DOCROOT.$kohana_modules;
$kohana_system = file_exists($kohana_system) ? $kohana_system : DOCROOT.$kohana_system;
// Define application and system paths
define('APPPATH', str_replace('\\', '/', realpath($kohana_application)).'/');
define('MODPATH', str_replace('\\', '/', realpath($kohana_modules)).'/');
define('SYSPATH', str_replace('\\', '/', realpath($kohana_system)).'/');
// Clean up
unset($kohana_application, $kohana_modules, $kohana_system);
if (file_exists(DOCROOT.'install'.EXT) AND is_readable(DOCROOT.'install'.EXT))
{
// Load the installation tests
include DOCROOT.'install'.EXT;
}
else
{
// Initialize Kohana
require APPPATH.'Bootstrap'.EXT;
}

View File

@ -0,0 +1,67 @@
(function($) {
var _current_path = "";
$.fn.gallery3_client = function() {
return this.each(function(i) {
ajaxifyLoginForm(this);
});
};
function ajaxifyLoginForm(obj) {
var login = $(obj).find("#g-login-form form");
if (login.length > 0) {
$(login).ajaxForm({
dataType: "json",
beforeSubmit: function(formData, form, options) {
form.find(":submit")
.addClass("ui-state-disabled")
.attr("disabled", "disabled");
return true;
},
success: function(data) {
$(obj).html(data.content);
if (data.status == "ok") {
initializeDetail(obj);
} else {
ajaxifyLoginForm(obj);
}
}
});
} else {
initializeDetail(obj);
}
};
function initializeDetail(obj) {
$(".ui-icon-plus", obj).live("click", function (event) {
var siblings = $("~ ul", this);
if (siblings.length > 0) {
siblings.show();
$(this).removeClass("ui-icon-plus");
$(this).addClass("ui-icon-minus");
} else {
var parent = $(this).parent("li");
$.get("/g3_client/index.php/g3_client/albums",
{path: $(parent).attr("ref")},
function(data, textStatus) {
$(parent).replaceWith(data);
});
}
});
$(".ui-icon-minus", obj).live("click", function (event) {
$("~ ul", this).hide();
$(this).removeClass("ui-icon-minus");
$(this).addClass("ui-icon-plus");
});
$(".tree-title", obj).click(function (event) {
$.get("/g3_client/index.php/g3_client/detail",
{path: $(this).parent("li").attr("ref")},
function(data, textStatus) {
$("#center").html(data);
});
$(".ui-selected").removeClass("ui-selected");
$(this).addClass("ui-selected");
});
$("#album_tree [ref=''] .tree-title:first").addClass("ui-selected");
};
})(jQuery);

45
web_client/js/jquery-ui.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,645 @@
/*
* jQuery Form Plugin
* version: 2.28 (10-MAY-2009)
* @requires jQuery v1.2.2 or later
*
* Examples and documentation at: http://malsup.com/jquery/form/
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*/
;(function($) {
/*
Usage Note:
-----------
Do not use both ajaxSubmit and ajaxForm on the same form. These
functions are intended to be exclusive. Use ajaxSubmit if you want
to bind your own submit handler to the form. For example,
$(document).ready(function() {
$('#myForm').bind('submit', function() {
$(this).ajaxSubmit({
target: '#output'
});
return false; // <-- important!
});
});
Use ajaxForm when you want the plugin to manage all the event binding
for you. For example,
$(document).ready(function() {
$('#myForm').ajaxForm({
target: '#output'
});
});
When using ajaxForm, the ajaxSubmit function will be invoked for you
at the appropriate time.
*/
/**
* ajaxSubmit() provides a mechanism for immediately submitting
* an HTML form using AJAX.
*/
$.fn.ajaxSubmit = function(options) {
// fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
if (!this.length) {
log('ajaxSubmit: skipping submit process - no element selected');
return this;
}
if (typeof options == 'function')
options = { success: options };
var url = $.trim(this.attr('action'));
if (url) {
// clean url (don't include hash vaue)
url = (url.match(/^([^#]+)/)||[])[1];
}
url = url || window.location.href || ''
options = $.extend({
url: url,
type: this.attr('method') || 'GET'
}, options || {});
// hook for manipulating the form data before it is extracted;
// convenient for use with rich editors like tinyMCE or FCKEditor
var veto = {};
this.trigger('form-pre-serialize', [this, options, veto]);
if (veto.veto) {
log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
return this;
}
// provide opportunity to alter form data before it is serialized
if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
log('ajaxSubmit: submit aborted via beforeSerialize callback');
return this;
}
var a = this.formToArray(options.semantic);
if (options.data) {
options.extraData = options.data;
for (var n in options.data) {
if(options.data[n] instanceof Array) {
for (var k in options.data[n])
a.push( { name: n, value: options.data[n][k] } );
}
else
a.push( { name: n, value: options.data[n] } );
}
}
// give pre-submit callback an opportunity to abort the submit
if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
log('ajaxSubmit: submit aborted via beforeSubmit callback');
return this;
}
// fire vetoable 'validate' event
this.trigger('form-submit-validate', [a, this, options, veto]);
if (veto.veto) {
log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
return this;
}
var q = $.param(a);
if (options.type.toUpperCase() == 'GET') {
options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
options.data = null; // data is null for 'get'
}
else
options.data = q; // data is the query string for 'post'
var $form = this, callbacks = [];
if (options.resetForm) callbacks.push(function() { $form.resetForm(); });
if (options.clearForm) callbacks.push(function() { $form.clearForm(); });
// perform a load on the target only if dataType is not provided
if (!options.dataType && options.target) {
var oldSuccess = options.success || function(){};
callbacks.push(function(data) {
$(options.target).html(data).each(oldSuccess, arguments);
});
}
else if (options.success)
callbacks.push(options.success);
options.success = function(data, status) {
for (var i=0, max=callbacks.length; i < max; i++)
callbacks[i].apply(options, [data, status, $form]);
};
// are there files to upload?
var files = $('input:file', this).fieldValue();
var found = false;
for (var j=0; j < files.length; j++)
if (files[j])
found = true;
var multipart = false;
// var mp = 'multipart/form-data';
// multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
// options.iframe allows user to force iframe mode
if (options.iframe || found || multipart) {
// hack to fix Safari hang (thanks to Tim Molendijk for this)
// see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
if (options.closeKeepAlive)
$.get(options.closeKeepAlive, fileUpload);
else
fileUpload();
}
else
$.ajax(options);
// fire 'notify' event
this.trigger('form-submit-notify', [this, options]);
return this;
// private function for handling file uploads (hat tip to YAHOO!)
function fileUpload() {
var form = $form[0];
/* (this breaks the watermark form uploader, turn it off for now)
if ($(':input[name=submit]', form).length) {
alert('Error: Form elements must not be named "submit".');
return;
}
*/
var opts = $.extend({}, $.ajaxSettings, options);
var s = $.extend(true, {}, $.extend(true, {}, $.ajaxSettings), opts);
var id = 'jqFormIO' + (new Date().getTime());
var $io = $('<iframe id="' + id + '" name="' + id + '" src="about:blank" />');
var io = $io[0];
$io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
var xhr = { // mock object
aborted: 0,
responseText: null,
responseXML: null,
status: 0,
statusText: 'n/a',
getAllResponseHeaders: function() {},
getResponseHeader: function() {},
setRequestHeader: function() {},
abort: function() {
this.aborted = 1;
$io.attr('src','about:blank'); // abort op in progress
}
};
var g = opts.global;
// trigger ajax global events so that activity/block indicators work like normal
if (g && ! $.active++) $.event.trigger("ajaxStart");
if (g) $.event.trigger("ajaxSend", [xhr, opts]);
if (s.beforeSend && s.beforeSend(xhr, s) === false) {
s.global && $.active--;
return;
}
if (xhr.aborted)
return;
var cbInvoked = 0;
var timedOut = 0;
// add submitting element to data if we know it
var sub = form.clk;
if (sub) {
var n = sub.name;
if (n && !sub.disabled) {
options.extraData = options.extraData || {};
options.extraData[n] = sub.value;
if (sub.type == "image") {
options.extraData[name+'.x'] = form.clk_x;
options.extraData[name+'.y'] = form.clk_y;
}
}
}
// take a breath so that pending repaints get some cpu time before the upload starts
setTimeout(function() {
// make sure form attrs are set
var t = $form.attr('target'), a = $form.attr('action');
// update form attrs in IE friendly way
form.setAttribute('target',id);
if (form.getAttribute('method') != 'POST')
form.setAttribute('method', 'POST');
if (form.getAttribute('action') != opts.url)
form.setAttribute('action', opts.url);
// ie borks in some cases when setting encoding
if (! options.skipEncodingOverride) {
$form.attr({
encoding: 'multipart/form-data',
enctype: 'multipart/form-data'
});
}
// support timout
if (opts.timeout)
setTimeout(function() { timedOut = true; cb(); }, opts.timeout);
// add "extra" data to form if provided in options
var extraInputs = [];
try {
if (options.extraData)
for (var n in options.extraData)
extraInputs.push(
$('<input type="hidden" name="'+n+'" value="'+options.extraData[n]+'" />')
.appendTo(form)[0]);
// add iframe to doc and submit the form
$io.appendTo('body');
io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
form.submit();
}
finally {
// reset attrs and remove "extra" input elements
form.setAttribute('action',a);
t ? form.setAttribute('target', t) : $form.removeAttr('target');
$(extraInputs).remove();
}
}, 10);
var nullCheckFlag = 0;
function cb() {
if (cbInvoked++) return;
io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);
var ok = true;
try {
if (timedOut) throw 'timeout';
// extract the server response from the iframe
var data, doc;
doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
if ((doc.body == null || doc.body.innerHTML == '') && !nullCheckFlag) {
// in some browsers (cough, Opera 9.2.x) the iframe DOM is not always traversable when
// the onload callback fires, so we give them a 2nd chance
nullCheckFlag = 1;
cbInvoked--;
setTimeout(cb, 100);
return;
}
xhr.responseText = doc.body ? doc.body.innerHTML : null;
xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
xhr.getResponseHeader = function(header){
var headers = {'content-type': opts.dataType};
return headers[header];
};
if (opts.dataType == 'json' || opts.dataType == 'script') {
var ta = doc.getElementsByTagName('textarea')[0];
xhr.responseText = ta ? ta.value : xhr.responseText;
}
else if (opts.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
xhr.responseXML = toXml(xhr.responseText);
}
data = $.httpData(xhr, opts.dataType);
}
catch(e){
ok = false;
$.handleError(opts, xhr, 'error', e);
}
// ordering of these callbacks/triggers is odd, but that's how $.ajax does it
if (ok) {
opts.success(data, 'success');
if (g) $.event.trigger("ajaxSuccess", [xhr, opts]);
}
if (g) $.event.trigger("ajaxComplete", [xhr, opts]);
if (g && ! --$.active) $.event.trigger("ajaxStop");
if (opts.complete) opts.complete(xhr, ok ? 'success' : 'error');
// clean up
setTimeout(function() {
$io.remove();
xhr.responseXML = null;
}, 100);
};
function toXml(s, doc) {
if (window.ActiveXObject) {
doc = new ActiveXObject('Microsoft.XMLDOM');
doc.async = 'false';
doc.loadXML(s);
}
else
doc = (new DOMParser()).parseFromString(s, 'text/xml');
return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null;
};
};
};
/**
* ajaxForm() provides a mechanism for fully automating form submission.
*
* The advantages of using this method instead of ajaxSubmit() are:
*
* 1: This method will include coordinates for <input type="image" /> elements (if the element
* is used to submit the form).
* 2. This method will include the submit element's name/value data (for the element that was
* used to submit the form).
* 3. This method binds the submit() method to the form for you.
*
* The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely
* passes the options argument along after properly binding events for submit elements and
* the form itself.
*/
$.fn.ajaxForm = function(options) {
return this.ajaxFormUnbind().bind('submit.form-plugin',function() {
$(this).ajaxSubmit(options);
return false;
}).each(function() {
// store options in hash
$(":submit,input:image", this).bind('click.form-plugin',function(e) {
var form = this.form;
form.clk = this;
if (this.type == 'image') {
if (e.offsetX != undefined) {
form.clk_x = e.offsetX;
form.clk_y = e.offsetY;
} else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin
var offset = $(this).offset();
form.clk_x = e.pageX - offset.left;
form.clk_y = e.pageY - offset.top;
} else {
form.clk_x = e.pageX - this.offsetLeft;
form.clk_y = e.pageY - this.offsetTop;
}
}
// clear form vars
setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 10);
});
});
};
// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
$.fn.ajaxFormUnbind = function() {
this.unbind('submit.form-plugin');
return this.each(function() {
$(":submit,input:image", this).unbind('click.form-plugin');
});
};
/**
* formToArray() gathers form element data into an array of objects that can
* be passed to any of the following ajax functions: $.get, $.post, or load.
* Each object in the array has both a 'name' and 'value' property. An example of
* an array for a simple login form might be:
*
* [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
*
* It is this array that is passed to pre-submit callback functions provided to the
* ajaxSubmit() and ajaxForm() methods.
*/
$.fn.formToArray = function(semantic) {
var a = [];
if (this.length == 0) return a;
var form = this[0];
var els = semantic ? form.getElementsByTagName('*') : form.elements;
if (!els) return a;
for(var i=0, max=els.length; i < max; i++) {
var el = els[i];
var n = el.name;
if (!n) continue;
if (semantic && form.clk && el.type == "image") {
// handle image inputs on the fly when semantic == true
if(!el.disabled && form.clk == el) {
a.push({name: n, value: $(el).val()});
a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
}
continue;
}
var v = $.fieldValue(el, true);
if (v && v.constructor == Array) {
for(var j=0, jmax=v.length; j < jmax; j++)
a.push({name: n, value: v[j]});
}
else if (v !== null && typeof v != 'undefined')
a.push({name: n, value: v});
}
if (!semantic && form.clk) {
// input type=='image' are not found in elements array! handle it here
var $input = $(form.clk), input = $input[0], n = input.name;
if (n && !input.disabled && input.type == 'image') {
a.push({name: n, value: $input.val()});
a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
}
}
return a;
};
/**
* Serializes form data into a 'submittable' string. This method will return a string
* in the format: name1=value1&amp;name2=value2
*/
$.fn.formSerialize = function(semantic) {
//hand off to jQuery.param for proper encoding
return $.param(this.formToArray(semantic));
};
/**
* Serializes all field elements in the jQuery object into a query string.
* This method will return a string in the format: name1=value1&amp;name2=value2
*/
$.fn.fieldSerialize = function(successful) {
var a = [];
this.each(function() {
var n = this.name;
if (!n) return;
var v = $.fieldValue(this, successful);
if (v && v.constructor == Array) {
for (var i=0,max=v.length; i < max; i++)
a.push({name: n, value: v[i]});
}
else if (v !== null && typeof v != 'undefined')
a.push({name: this.name, value: v});
});
//hand off to jQuery.param for proper encoding
return $.param(a);
};
/**
* Returns the value(s) of the element in the matched set. For example, consider the following form:
*
* <form><fieldset>
* <input name="A" type="text" />
* <input name="A" type="text" />
* <input name="B" type="checkbox" value="B1" />
* <input name="B" type="checkbox" value="B2"/>
* <input name="C" type="radio" value="C1" />
* <input name="C" type="radio" value="C2" />
* </fieldset></form>
*
* var v = $(':text').fieldValue();
* // if no values are entered into the text inputs
* v == ['','']
* // if values entered into the text inputs are 'foo' and 'bar'
* v == ['foo','bar']
*
* var v = $(':checkbox').fieldValue();
* // if neither checkbox is checked
* v === undefined
* // if both checkboxes are checked
* v == ['B1', 'B2']
*
* var v = $(':radio').fieldValue();
* // if neither radio is checked
* v === undefined
* // if first radio is checked
* v == ['C1']
*
* The successful argument controls whether or not the field element must be 'successful'
* (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
* The default value of the successful argument is true. If this value is false the value(s)
* for each element is returned.
*
* Note: This method *always* returns an array. If no valid value can be determined the
* array will be empty, otherwise it will contain one or more values.
*/
$.fn.fieldValue = function(successful) {
for (var val=[], i=0, max=this.length; i < max; i++) {
var el = this[i];
var v = $.fieldValue(el, successful);
if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length))
continue;
v.constructor == Array ? $.merge(val, v) : val.push(v);
}
return val;
};
/**
* Returns the value of the field element.
*/
$.fieldValue = function(el, successful) {
var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
if (typeof successful == 'undefined') successful = true;
if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
(t == 'checkbox' || t == 'radio') && !el.checked ||
(t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
tag == 'select' && el.selectedIndex == -1))
return null;
if (tag == 'select') {
var index = el.selectedIndex;
if (index < 0) return null;
var a = [], ops = el.options;
var one = (t == 'select-one');
var max = (one ? index+1 : ops.length);
for(var i=(one ? index : 0); i < max; i++) {
var op = ops[i];
if (op.selected) {
var v = op.value;
if (!v) // extra pain for IE...
v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
if (one) return v;
a.push(v);
}
}
return a;
}
return el.value;
};
/**
* Clears the form data. Takes the following actions on the form's input fields:
* - input text fields will have their 'value' property set to the empty string
* - select elements will have their 'selectedIndex' property set to -1
* - checkbox and radio inputs will have their 'checked' property set to false
* - inputs of type submit, button, reset, and hidden will *not* be effected
* - button elements will *not* be effected
*/
$.fn.clearForm = function() {
return this.each(function() {
$('input,select,textarea', this).clearFields();
});
};
/**
* Clears the selected form elements.
*/
$.fn.clearFields = $.fn.clearInputs = function() {
return this.each(function() {
var t = this.type, tag = this.tagName.toLowerCase();
if (t == 'text' || t == 'password' || tag == 'textarea')
this.value = '';
else if (t == 'checkbox' || t == 'radio')
this.checked = false;
else if (tag == 'select')
this.selectedIndex = -1;
});
};
/**
* Resets the form data. Causes all form elements to be reset to their original value.
*/
$.fn.resetForm = function() {
return this.each(function() {
// guard against an input with the name of 'reset'
// note that IE reports the reset function as an 'object'
if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType))
this.reset();
});
};
/**
* Enables or disables any matching elements.
*/
$.fn.enable = function(b) {
if (b == undefined) b = true;
return this.each(function() {
this.disabled = !b;
});
};
/**
* Checks/unchecks any matching checkboxes or radio buttons and
* selects/deselects and matching option elements.
*/
$.fn.selected = function(select) {
if (select == undefined) select = true;
return this.each(function() {
var t = this.type;
if (t == 'checkbox' || t == 'radio')
this.checked = select;
else if (this.tagName.toLowerCase() == 'option') {
var $sel = $(this).parent('select');
if (select && $sel[0] && $sel[0].type == 'select-one') {
// deselect all other options
$sel.find('option').selected(false);
}
this.selected = select;
}
});
};
// helper fn for console logging
// set $.fn.ajaxSubmit.debug to true to enable debug logging
function log() {
if ($.fn.ajaxSubmit.debug && window.console && window.console.log)
window.console.log('[jquery.form] ' + Array.prototype.join.call(arguments,''));
};
})(jQuery);

19
web_client/js/jquery.js vendored Normal file

File diff suppressed because one or more lines are too long

BIN
web_client/kohana.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -0,0 +1,31 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* @package Cache
*
* Cache settings, defined as arrays, or "groups". If no group name is
* used when loading the cache library, the group named "default" will be used.
*
* Each group can be used independently, and multiple groups can be used at once.
*
* Group Options:
* driver - Cache backend driver. Kohana comes with file, database, and memcache drivers.
* > File cache is fast and reliable, but requires many filesystem lookups.
* > Database cache can be used to cache items remotely, but is slower.
* > Memcache is very high performance, but prevents cache tags from being used.
*
* params - Driver parameters, specific to each driver.
*
* lifetime - Default lifetime of caches in seconds. By default caches are stored for
* thirty minutes. Specific lifetime can also be set when creating a new cache.
* Setting this to 0 will never automatically delete caches.
*
* prefix - Adds a prefix to all keys and tags. This can have a severe performance impact.
*
*/
$config['default'] = array
(
'driver' => 'file',
'params' => array('directory' => APPPATH.'cache', 'gc_probability' => 1000),
'lifetime' => 1800,
'prefix' => NULL
);

View File

@ -0,0 +1,38 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* @package Core
*
* Domain, to restrict the cookie to a specific website domain. For security,
* you are encouraged to set this option. An empty setting allows the cookie
* to be read by any website domain.
*/
$config['domain'] = '';
/**
* Restrict cookies to a specific path, typically the installation directory.
*/
$config['path'] = '/';
/**
* Lifetime of the cookie. A setting of 0 makes the cookie active until the
* users browser is closed or the cookie is deleted.
*/
$config['expire'] = 0;
/**
* Enable this option to only allow the cookie to be read when using the a
* secure protocol.
*/
$config['secure'] = FALSE;
/**
* Enable this option to make the cookie accessible only through the
* HTTP protocol (e.g. no javascript access). This is not supported by all browsers.
*/
$config['httponly'] = FALSE;
/**
* Cookie salt for signed cookies.
* Make sure you change this to a unique value.
*/
$config['salt'] = 'K0hAN4 15 Th3 B357';

View File

@ -0,0 +1,60 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Credit card validation configuration.
*
* Options for each credit card:
* length - All the allowed card number lengths, in a comma separated string
* prefix - The digits the card needs to start with, in regex format
* luhn - Enable or disable card number validation by the Luhn algorithm
*/
$config = array
(
'default' => array
(
'length' => '13,14,15,16,17,18,19',
'prefix' => '',
'luhn' => TRUE
),
'american express' => array
(
'length' => '15',
'prefix' => '3[47]',
'luhn' => TRUE
),
'diners club' => array
(
'length' => '14,16',
'prefix' => '36|55|30[0-5]',
'luhn' => TRUE
),
'discover' => array
(
'length' => '16',
'prefix' => '6(?:5|011)',
'luhn' => TRUE,
),
'jcb' => array
(
'length' => '15,16',
'prefix' => '3|1800|2131',
'luhn' => TRUE
),
'maestro' => array
(
'length' => '16,18',
'prefix' => '50(?:20|38)|6(?:304|759)',
'luhn' => TRUE
),
'mastercard' => array
(
'length' => '16',
'prefix' => '5[1-5]',
'luhn' => TRUE
),
'visa' => array
(
'length' => '13,16',
'prefix' => '4',
'luhn' => TRUE
),
);

View File

@ -0,0 +1,46 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* @package Database
*
* Database connection settings, defined as arrays, or "groups". If no group
* name is used when loading the database library, the group named "default"
* will be used.
*
* Each group can be connected to independently, and multiple groups can be
* connected at once.
*
* Group Options:
* benchmark - Enable or disable database benchmarking
* persistent - Enable or disable a persistent connection
* connection - Array of connection specific parameters; alternatively,
* you can use a DSN though it is not as fast and certain
* characters could create problems (like an '@' character
* in a password):
* 'connection' => 'mysql://dbuser:secret@localhost/kohana'
* character_set - Database character set
* table_prefix - Database table prefix
* object - Enable or disable object results
* cache - Enable or disable query caching
* escape - Enable automatic query builder escaping
*/
$config['default'] = array
(
'benchmark' => FALSE,
'persistent' => FALSE,
'connection' => array
(
'type' => 'mysql',
'user' => 'dbuser',
'pass' => 'p@ssw0rd',
'host' => 'localhost',
'port' => FALSE,
'socket' => FALSE,
'database' => 'kohana',
'params' => NULL,
),
'character_set' => 'utf8',
'table_prefix' => '',
'object' => TRUE,
'cache' => FALSE,
'escape' => TRUE
);

View File

@ -0,0 +1,31 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* @package Encrypt
*
* Encrypt configuration is defined in groups which allows you to easily switch
* between different encryption settings for different uses.
* Note: all groups inherit and overwrite the default group.
*
* Group Options:
* key - Encryption key used to do encryption and decryption. The default option
* should never be used for a production website.
*
* For best security, your encryption key should be at least 16 characters
* long and contain letters, numbers, and symbols.
* @note Do not use a hash as your key. This significantly lowers encryption entropy.
*
* mode - MCrypt encryption mode. By default, MCRYPT_MODE_NOFB is used. This mode
* offers initialization vector support, is suited to short strings, and
* produces the shortest encrypted output.
* @see http://php.net/mcrypt
*
* cipher - MCrypt encryption cipher. By default, the MCRYPT_RIJNDAEL_128 cipher is used.
* This is also known as 128-bit AES.
* @see http://php.net/mcrypt
*/
$config['default'] = array
(
'key' => 'K0H@NA+PHP_7hE-SW!FtFraM3w0R|<',
'mode' => MCRYPT_MODE_NOFB,
'cipher' => MCRYPT_RIJNDAEL_128
);

View File

@ -0,0 +1,7 @@
<?php
/**
* If using HTMLPurifier then this option allows setting an
* alternative path for the cache data. Note that that path
* must be an absolute location.
*/
$config['cache'] = '/tmp/htmlpurifier';

View File

@ -0,0 +1,19 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
// HTTP-EQUIV type meta tags
$config['meta_equiv'] = array
(
'cache-control',
'content-type', 'content-script-type', 'content-style-type',
'content-disposition',
'content-language',
'default-style',
'expires',
'ext-cache',
'pics-label',
'pragma',
'refresh',
'set-cookie',
'vary',
'window-target',
);

View File

@ -0,0 +1,13 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* @package Image
*
* Driver name. Default: GD
*/
$config['driver'] = 'GD';
/**
* Driver parameters:
* ImageMagick - set the "directory" parameter to your ImageMagick installation directory
*/
$config['params'] = array();

View File

@ -0,0 +1,60 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
$config['uncountable'] = array
(
'access',
'advice',
'art',
'baggage',
'dances',
'data',
'equipment',
'fish',
'fuel',
'furniture',
'food',
'heat',
'honey',
'homework',
'impatience',
'information',
'knowledge',
'luggage',
'metadata',
'money',
'music',
'news',
'patience',
'progress',
'pollution',
'research',
'rice',
'sand',
'series',
'sheep',
'sms',
'species',
'staff',
'toothpaste',
'traffic',
'understanding',
'water',
'weather',
'work',
);
$config['irregular'] = array
(
'child' => 'children',
'clothes' => 'clothing',
'man' => 'men',
'movie' => 'movies',
'person' => 'people',
'woman' => 'women',
'mouse' => 'mice',
'goose' => 'geese',
'ox' => 'oxen',
'leaf' => 'leaves',
'course' => 'courses',
'size' => 'sizes',
);

View File

@ -0,0 +1,17 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* @package Core
*
* Default language locale name(s).
* First item must be a valid i18n directory name, subsequent items are alternative locales
* for OS's that don't support the first (e.g. Windows). The first valid locale in the array will be used.
* @see http://php.net/setlocale
*/
$config['language'] = array('en_US', 'English_United States');
/**
* Locale timezone. Defaults to the timezone you have set in your php config
* This cannot be left empty, a valid timezone is required!
* @see http://php.net/timezones
*/
$config['timezone'] = ini_get('date.timezone');

View File

@ -0,0 +1,19 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
// Different log levels
$config['log_levels'] = array
(
'error' => 1,
'alert' => 2,
'info' => 3,
'debug' => 4,
);
// See different log levels above
$config['log_threshold'] = 1;
$config['date_format'] = 'Y-m-d H:i:s P';
// We can define multiple logging backends at the same time.
$config['drivers'] = array('file');

View File

@ -0,0 +1,24 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Database config group to store log messages
*/
$config['group'] = 'default';
/**
* Database table to store log messages in
*/
$config['table'] = 'logs';
/* MySQL Database schema:
CREATE TABLE IF NOT EXISTS `logs` (
`id` int(10) unsigned NOT NULL auto_increment,
`date` int(11) NOT NULL,
`level` varchar(5) NOT NULL,
`message` text NOT NULL,
PRIMARY KEY (`id`),
KEY `date` (`date`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
*/

View File

@ -0,0 +1,11 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Message logging directory.
*/
$config['log_directory'] = APPPATH.'logs';
/**
* Permissions of the log file
*/
$config['posix_permissions'] = 0644;

View File

@ -0,0 +1,6 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Ident string added to each syslog message
*/
$config['ident'] = 'KohanaPHP';

View File

@ -0,0 +1,224 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* @package Core
*
* A list of mime types. Our list is generally more complete and accurate than
* the operating system MIME list.
*
* If there are any missing options, please create a ticket on our issue tracker,
* http://dev.kohanaphp.com/projects/kohana2. Be sure to give the filename and
* expected MIME type, as well as any additional information you can provide.
*/
$config = array
(
'323' => array('text/h323'),
'7z' => array('application/x-7z-compressed'),
'abw' => array('application/x-abiword'),
'acx' => array('application/internet-property-stream'),
'ai' => array('application/postscript'),
'aif' => array('audio/x-aiff'),
'aifc' => array('audio/x-aiff'),
'aiff' => array('audio/x-aiff'),
'asf' => array('video/x-ms-asf'),
'asr' => array('video/x-ms-asf'),
'asx' => array('video/x-ms-asf'),
'atom' => array('application/atom+xml'),
'avi' => array('video/avi', 'video/msvideo', 'video/x-msvideo'),
'bin' => array('application/octet-stream','application/macbinary'),
'bmp' => array('image/bmp'),
'c' => array('text/x-csrc'),
'c++' => array('text/x-c++src'),
'cab' => array('application/x-cab'),
'cc' => array('text/x-c++src'),
'cda' => array('application/x-cdf'),
'class' => array('application/octet-stream'),
'cpp' => array('text/x-c++src'),
'cpt' => array('application/mac-compactpro'),
'csh' => array('text/x-csh'),
'css' => array('text/css'),
'csv' => array('text/x-comma-separated-values', 'application/vnd.ms-excel', 'text/comma-separated-values', 'text/csv'),
'dbk' => array('application/docbook+xml'),
'dcr' => array('application/x-director'),
'deb' => array('application/x-debian-package'),
'diff' => array('text/x-diff'),
'dir' => array('application/x-director'),
'divx' => array('video/divx'),
'dll' => array('application/octet-stream', 'application/x-msdos-program'),
'dmg' => array('application/x-apple-diskimage'),
'dms' => array('application/octet-stream'),
'doc' => array('application/msword'),
'dvi' => array('application/x-dvi'),
'dxr' => array('application/x-director'),
'eml' => array('message/rfc822'),
'eps' => array('application/postscript'),
'evy' => array('application/envoy'),
'exe' => array('application/x-msdos-program', 'application/octet-stream'),
'fla' => array('application/octet-stream'),
'flac' => array('application/x-flac'),
'flc' => array('video/flc'),
'fli' => array('video/fli'),
'flv' => array('video/x-flv'),
'gif' => array('image/gif'),
'gtar' => array('application/x-gtar'),
'gz' => array('application/x-gzip'),
'h' => array('text/x-chdr'),
'h++' => array('text/x-c++hdr'),
'hh' => array('text/x-c++hdr'),
'hpp' => array('text/x-c++hdr'),
'hqx' => array('application/mac-binhex40'),
'hs' => array('text/x-haskell'),
'htm' => array('text/html'),
'html' => array('text/html'),
'ico' => array('image/x-icon'),
'ics' => array('text/calendar'),
'iii' => array('application/x-iphone'),
'ins' => array('application/x-internet-signup'),
'iso' => array('application/x-iso9660-image'),
'isp' => array('application/x-internet-signup'),
'jar' => array('application/java-archive'),
'java' => array('application/x-java-applet'),
'jpe' => array('image/jpeg', 'image/pjpeg'),
'jpeg' => array('image/jpeg', 'image/pjpeg'),
'jpg' => array('image/jpeg', 'image/pjpeg'),
'js' => array('application/x-javascript'),
'json' => array('application/json'),
'latex' => array('application/x-latex'),
'lha' => array('application/octet-stream'),
'log' => array('text/plain', 'text/x-log'),
'lzh' => array('application/octet-stream'),
'm4a' => array('audio/mpeg'),
'm4p' => array('video/mp4v-es'),
'm4v' => array('video/mp4'),
'man' => array('application/x-troff-man'),
'mdb' => array('application/x-msaccess'),
'midi' => array('audio/midi'),
'mid' => array('audio/midi'),
'mif' => array('application/vnd.mif'),
'mka' => array('audio/x-matroska'),
'mkv' => array('video/x-matroska'),
'mov' => array('video/quicktime'),
'movie' => array('video/x-sgi-movie'),
'mp2' => array('audio/mpeg'),
'mp3' => array('audio/mpeg'),
'mp4' => array('application/mp4','audio/mp4','video/mp4'),
'mpa' => array('video/mpeg'),
'mpe' => array('video/mpeg'),
'mpeg' => array('video/mpeg'),
'mpg' => array('video/mpeg'),
'mpg4' => array('video/mp4'),
'mpga' => array('audio/mpeg'),
'mpp' => array('application/vnd.ms-project'),
'mpv' => array('video/x-matroska'),
'mpv2' => array('video/mpeg'),
'ms' => array('application/x-troff-ms'),
'msg' => array('application/msoutlook','application/x-msg'),
'msi' => array('application/x-msi'),
'nws' => array('message/rfc822'),
'oda' => array('application/oda'),
'odb' => array('application/vnd.oasis.opendocument.database'),
'odc' => array('application/vnd.oasis.opendocument.chart'),
'odf' => array('application/vnd.oasis.opendocument.forumla'),
'odg' => array('application/vnd.oasis.opendocument.graphics'),
'odi' => array('application/vnd.oasis.opendocument.image'),
'odm' => array('application/vnd.oasis.opendocument.text-master'),
'odp' => array('application/vnd.oasis.opendocument.presentation'),
'ods' => array('application/vnd.oasis.opendocument.spreadsheet'),
'odt' => array('application/vnd.oasis.opendocument.text'),
'oga' => array('audio/ogg'),
'ogg' => array('application/ogg'),
'ogv' => array('video/ogg'),
'otg' => array('application/vnd.oasis.opendocument.graphics-template'),
'oth' => array('application/vnd.oasis.opendocument.web'),
'otp' => array('application/vnd.oasis.opendocument.presentation-template'),
'ots' => array('application/vnd.oasis.opendocument.spreadsheet-template'),
'ott' => array('application/vnd.oasis.opendocument.template'),
'p' => array('text/x-pascal'),
'pas' => array('text/x-pascal'),
'patch' => array('text/x-diff'),
'pbm' => array('image/x-portable-bitmap'),
'pdf' => array('application/pdf', 'application/x-download'),
'php' => array('application/x-httpd-php'),
'php3' => array('application/x-httpd-php'),
'php4' => array('application/x-httpd-php'),
'php5' => array('application/x-httpd-php'),
'phps' => array('application/x-httpd-php-source'),
'phtml' => array('application/x-httpd-php'),
'pl' => array('text/x-perl'),
'pm' => array('text/x-perl'),
'png' => array('image/png', 'image/x-png'),
'po' => array('text/x-gettext-translation'),
'pot' => array('application/vnd.ms-powerpoint'),
'pps' => array('application/vnd.ms-powerpoint'),
'ppt' => array('application/powerpoint'),
'ps' => array('application/postscript'),
'psd' => array('application/x-photoshop', 'image/x-photoshop'),
'pub' => array('application/x-mspublisher'),
'py' => array('text/x-python'),
'qt' => array('video/quicktime'),
'ra' => array('audio/x-realaudio'),
'ram' => array('audio/x-realaudio', 'audio/x-pn-realaudio'),
'rar' => array('application/rar'),
'rgb' => array('image/x-rgb'),
'rm' => array('audio/x-pn-realaudio'),
'rpm' => array('audio/x-pn-realaudio-plugin', 'application/x-redhat-package-manager'),
'rss' => array('application/rss+xml'),
'rtf' => array('text/rtf'),
'rtx' => array('text/richtext'),
'rv' => array('video/vnd.rn-realvideo'),
'sea' => array('application/octet-stream'),
'sh' => array('text/x-sh'),
'shtml' => array('text/html'),
'sit' => array('application/x-stuffit'),
'smi' => array('application/smil'),
'smil' => array('application/smil'),
'so' => array('application/octet-stream'),
'src' => array('application/x-wais-source'),
'svg' => array('image/svg+xml'),
'swf' => array('application/x-shockwave-flash'),
't' => array('application/x-troff'),
'tar' => array('application/x-tar'),
'tcl' => array('text/x-tcl'),
'tex' => array('application/x-tex'),
'text' => array('text/plain'),
'texti' => array('application/x-texinfo'),
'textinfo' => array('application/x-texinfo'),
'tgz' => array('application/x-tar'),
'tif' => array('image/tiff'),
'tiff' => array('image/tiff'),
'torrent' => array('application/x-bittorrent'),
'tr' => array('application/x-troff'),
'tsv' => array('text/tab-separated-values'),
'txt' => array('text/plain'),
'wav' => array('audio/x-wav'),
'wax' => array('audio/x-ms-wax'),
'wbxml' => array('application/wbxml'),
'wm' => array('video/x-ms-wm'),
'wma' => array('audio/x-ms-wma'),
'wmd' => array('application/x-ms-wmd'),
'wmlc' => array('application/wmlc'),
'wmv' => array('video/x-ms-wmv', 'application/octet-stream'),
'wmx' => array('video/x-ms-wmx'),
'wmz' => array('application/x-ms-wmz'),
'word' => array('application/msword', 'application/octet-stream'),
'wp5' => array('application/wordperfect5.1'),
'wpd' => array('application/vnd.wordperfect'),
'wvx' => array('video/x-ms-wvx'),
'xbm' => array('image/x-xbitmap'),
'xcf' => array('image/xcf'),
'xhtml' => array('application/xhtml+xml'),
'xht' => array('application/xhtml+xml'),
'xl' => array('application/excel', 'application/vnd.ms-excel'),
'xla' => array('application/excel', 'application/vnd.ms-excel'),
'xlc' => array('application/excel', 'application/vnd.ms-excel'),
'xlm' => array('application/excel', 'application/vnd.ms-excel'),
'xls' => array('application/excel', 'application/vnd.ms-excel'),
'xlt' => array('application/excel', 'application/vnd.ms-excel'),
'xml' => array('text/xml'),
'xof' => array('x-world/x-vrml'),
'xpm' => array('image/x-xpixmap'),
'xsl' => array('text/xml'),
'xvid' => array('video/x-xvid'),
'xwd' => array('image/x-xwindowdump'),
'z' => array('application/x-compress'),
'zip' => array('application/x-zip', 'application/zip', 'application/x-zip-compressed')
);

View File

@ -0,0 +1,12 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* @package Profiler
*
* Array of section names to display in the Profiler, TRUE to display all of them.
* Built in sections are benchmarks, database, session, post and cookies, custom sections can be used too.
*/
$config['show'] = TRUE;
$config['time_decimals'] = 3;
$config['memory_decimals'] = 2;

View File

@ -0,0 +1,7 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* @package Core
*
* Sets the default route to "welcome"
*/
$config['_default'] = 'welcome';

View File

@ -0,0 +1,48 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* @package Session
*
* Session driver name.
*/
$config['driver'] = 'cookie';
/**
* Session storage parameter, used by drivers.
*/
$config['storage'] = '';
/**
* Session name.
* It must contain only alphanumeric characters and underscores. At least one letter must be present.
*/
$config['name'] = 'kohanasession';
/**
* Session parameters to validate: user_agent, ip_address, expiration.
*/
$config['validate'] = array('user_agent');
/**
* Enable or disable session encryption.
* Note: this has no effect on the native session driver.
*/
$config['encryption'] = FALSE;
/**
* Session lifetime. Number of seconds that each session will last.
* A value of 0 will keep the session active until the browser is closed (with a limit of 24h).
*/
$config['expiration'] = 7200;
/**
* Number of page loads before the session id is regenerated.
* A value of 0 will disable automatic session id regeneration.
* NOTE: Enabling automatic session regeneration can cause a race condition see the
* docs for details: http://docs.kohanaphp.com/libraries/session#regenerate
*/
$config['regenerate'] = 0;
/**
* Percentage probability that the gc (garbage collection) routine is started.
*/
$config['gc_probability'] = 2;

View File

@ -0,0 +1,93 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* @package Database
*
* SQL data types. If there are missing values, please report them:
*
* @link http://dev.kohanaphp.com/projects/kohana2
*/
$config = array
(
// SQL-92
'bit' => array('type' => 'string', 'exact' => TRUE),
'bit varying' => array('type' => 'string'),
'character' => array('type' => 'string', 'exact' => TRUE),
'character varying' => array('type' => 'string'),
'date' => array('type' => 'string'),
'decimal' => array('type' => 'float', 'exact' => TRUE),
'double precision' => array('type' => 'float'),
'float' => array('type' => 'float'),
'integer' => array('type' => 'int', 'min' => -2147483648, 'max' => 2147483647),
'interval' => array('type' => 'string'),
'national character' => array('type' => 'string', 'exact' => TRUE),
'national character varying' => array('type' => 'string'),
'numeric' => array('type' => 'float', 'exact' => TRUE),
'real' => array('type' => 'float'),
'smallint' => array('type' => 'int', 'min' => -32768, 'max' => 32767),
'time' => array('type' => 'string'),
'time with time zone' => array('type' => 'string'),
'timestamp' => array('type' => 'string'),
'timestamp with time zone' => array('type' => 'string'),
// SQL:1999
//'array','ref','row'
'binary large object' => array('type' => 'string', 'binary' => TRUE),
'boolean' => array('type' => 'boolean'),
'character large object' => array('type' => 'string'),
'national character large object' => array('type' => 'string'),
// SQL:2003
'bigint' => array('type' => 'int', 'min' => -9223372036854775808, 'max' => 9223372036854775807),
// SQL:2008
'binary' => array('type' => 'string', 'binary' => TRUE, 'exact' => TRUE),
'binary varying' => array('type' => 'string', 'binary' => TRUE),
// MySQL
'bigint unsigned' => array('type' => 'int', 'min' => 0, 'max' => 18446744073709551615),
'decimal unsigned' => array('type' => 'float', 'exact' => TRUE, 'min' => 0.0),
'double unsigned' => array('type' => 'float', 'min' => 0.0),
'float unsigned' => array('type' => 'float', 'min' => 0.0),
'integer unsigned' => array('type' => 'int', 'min' => 0, 'max' => 4294967295),
'mediumint' => array('type' => 'int', 'min' => -8388608, 'max' => 8388607),
'mediumint unsigned' => array('type' => 'int', 'min' => 0, 'max' => 16777215),
'real unsigned' => array('type' => 'float', 'min' => 0.0),
'smallint unsigned' => array('type' => 'int', 'min' => 0, 'max' => 65535),
'text' => array('type' => 'string'),
'tinyint' => array('type' => 'int', 'min' => -128, 'max' => 127),
'tinyint unsigned' => array('type' => 'int', 'min' => 0, 'max' => 255),
'year' => array('type' => 'string'),
);
// SQL-92
$config['char'] = $config['character'];
$config['char varying'] = $config['character varying'];
$config['dec'] = $config['decimal'];
$config['int'] = $config['integer'];
$config['nchar'] = $config['national char'] = $config['national character'];
$config['nchar varying'] = $config['national char varying'] = $config['national character varying'];
$config['varchar'] = $config['character varying'];
// SQL:1999
$config['blob'] = $config['binary large object'];
$config['clob'] = $config['char large object'] = $config['character large object'];
$config['nclob'] = $config['nchar large object'] = $config['national character large object'];
$config['time without time zone'] = $config['time'];
$config['timestamp without time zone'] = $config['timestamp'];
// SQL:2008
$config['varbinary'] = $config['binary varying'];
// MySQL
$config['bool'] = $config['boolean'];
$config['datetime'] = $config['timestamp'];
$config['double'] = $config['double precision'];
$config['double precision unsigned'] = $config['double unsigned'];
$config['enum'] = $config['set'] = $config['character varying'];
$config['fixed'] = $config['decimal'];
$config['fixed unsigned'] = $config['decimal unsigned'];
$config['int unsigned'] = $config['integer unsigned'];
$config['longblob'] = $config['mediumblob'] = $config['tinyblob'] = $config['binary large object'];
$config['longtext'] = $config['mediumtext'] = $config['tinytext'] = $config['text'];
$config['numeric unsigned'] = $config['decimal unsigned'];
$config['nvarchar'] = $config['national varchar'] = $config['national character varying'];

View File

@ -0,0 +1,17 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* @package Core
*
* This path is relative to your index file. Absolute paths are also supported.
*/
$config['directory'] = DOCROOT.'upload';
/**
* Enable or disable directory creation.
*/
$config['create_directories'] = FALSE;
/**
* Remove spaces from uploaded filenames.
*/
$config['remove_spaces'] = TRUE;

View File

@ -0,0 +1,112 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* @package Core
*
* This file contains four arrays of user agent data. It is used by the
* User Agent library to help identify browser, platform, robot, and
* mobile device data. The array keys are used to identify the device
* and the array values are used to set the actual name of the item.
*/
$config['platform'] = array
(
'windows nt 6.0' => 'Windows Vista',
'windows nt 5.2' => 'Windows 2003',
'windows nt 5.0' => 'Windows 2000',
'windows nt 5.1' => 'Windows XP',
'windows nt 4.0' => 'Windows NT',
'winnt4.0' => 'Windows NT',
'winnt 4.0' => 'Windows NT',
'winnt' => 'Windows NT',
'windows 98' => 'Windows 98',
'win98' => 'Windows 98',
'windows 95' => 'Windows 95',
'win95' => 'Windows 95',
'windows' => 'Unknown Windows OS',
'os x' => 'Mac OS X',
'intel mac' => 'Intel Mac',
'ppc mac' => 'PowerPC Mac',
'powerpc' => 'PowerPC',
'ppc' => 'PowerPC',
'cygwin' => 'Cygwin',
'linux' => 'Linux',
'debian' => 'Debian',
'openvms' => 'OpenVMS',
'sunos' => 'Sun Solaris',
'amiga' => 'Amiga',
'beos' => 'BeOS',
'apachebench' => 'ApacheBench',
'freebsd' => 'FreeBSD',
'netbsd' => 'NetBSD',
'bsdi' => 'BSDi',
'openbsd' => 'OpenBSD',
'os/2' => 'OS/2',
'warp' => 'OS/2',
'aix' => 'AIX',
'irix' => 'Irix',
'osf' => 'DEC OSF',
'hp-ux' => 'HP-UX',
'hurd' => 'GNU/Hurd',
'unix' => 'Unknown Unix OS',
);
// The order of this array should NOT be changed. Many browsers return
// multiple browser types so we want to identify the sub-type first.
$config['browser'] = array
(
'Opera' => 'Opera',
'MSIE' => 'Internet Explorer',
'Internet Explorer' => 'Internet Explorer',
'Shiira' => 'Shiira',
'Firefox' => 'Firefox',
'Chimera' => 'Chimera',
'Phoenix' => 'Phoenix',
'Firebird' => 'Firebird',
'Camino' => 'Camino',
'Netscape' => 'Netscape',
'OmniWeb' => 'OmniWeb',
'Chrome' => 'Chrome',
'Safari' => 'Safari',
'Konqueror' => 'Konqueror',
'Epiphany' => 'Epiphany',
'Galeon' => 'Galeon',
'Mozilla' => 'Mozilla',
'icab' => 'iCab',
'lynx' => 'Lynx',
'links' => 'Links',
'hotjava' => 'HotJava',
'amaya' => 'Amaya',
'IBrowse' => 'IBrowse',
);
$config['mobile'] = array
(
'mobileexplorer' => 'Mobile Explorer',
'openwave' => 'Open Wave',
'opera mini' => 'Opera Mini',
'operamini' => 'Opera Mini',
'elaine' => 'Palm',
'palmsource' => 'Palm',
'digital paths' => 'Palm',
'avantgo' => 'Avantgo',
'xiino' => 'Xiino',
'palmscape' => 'Palmscape',
'nokia' => 'Nokia',
'ericsson' => 'Ericsson',
'blackBerry' => 'BlackBerry',
'motorola' => 'Motorola',
'iphone' => 'iPhone',
'android' => 'Android',
);
// There are hundreds of bots but these are the most common.
$config['robot'] = array
(
'googlebot' => 'Googlebot',
'msnbot' => 'MSNBot',
'slurp' => 'Inktomi Slurp',
'yahoo' => 'Yahoo',
'askjeeves' => 'AskJeeves',
'fastcrawler' => 'FastCrawler',
'infoseek' => 'InfoSeek Robot 1.0',
'lycos' => 'Lycos',
);

View File

@ -0,0 +1,18 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* @package Core
*
* Allowed non-php view types. Most file extensions are supported.
* Do not forget to add a valid MIME type in mimes.php
*/
$config['allowed_filetypes'] = array
(
'gif',
'jpg', 'jpeg',
'png',
'tif', 'tiff',
'swf',
'htm', 'html',
'css',
'js'
);

View File

@ -0,0 +1,23 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Outputs the dynamic Captcha resource.
* Usage: Call the Captcha controller from a view, e.g.
* <img src="<?php echo url::site('captcha') ?>" />
*
* $Id: captcha.php 4679 2009-11-10 01:45:52Z isaiah $
*
* @package Captcha
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class Captcha_Controller extends Controller {
public function __call($method, $args)
{
// Output the Captcha challenge resource (no html)
// Pull the config group name from the URL
Captcha::factory($this->uri->segment(2))->render(FALSE);
}
} // End Captcha_Controller

View File

@ -0,0 +1,54 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Allows a template to be automatically loaded and displayed. Display can be
* dynamically turned off in the controller methods, and the template file
* can be overloaded.
*
* To use it, declare your controller to extend this class:
* `class Your_Controller extends Template_Controller`
*
* $Id: template.php 4679 2009-11-10 01:45:52Z isaiah $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
abstract class Template_Controller extends Controller {
// Template view name
public $template = 'template';
// Default to do auto-rendering
public $auto_render = TRUE;
/**
* Template loading and setup routine.
*/
public function __construct()
{
parent::__construct();
// Load the template
$this->template = new View($this->template);
if ($this->auto_render == TRUE)
{
// Render the template immediately after the controller method
Event::add('system.post_controller', array($this, '_render'));
}
}
/**
* Render the loaded template.
*/
public function _render()
{
if ($this->auto_render == TRUE)
{
// Render the template when the class is destroyed
$this->template->render(TRUE);
}
}
} // End Template_Controller

View File

@ -0,0 +1,128 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Simple benchmarking.
*
* $Id: Benchmark.php 4679 2009-11-10 01:45:52Z isaiah $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
final class Benchmark {
// Benchmark timestamps
private static $marks;
/**
* Set a benchmark start point.
*
* @param string benchmark name
* @return void
*/
public static function start($name)
{
if (isset(self::$marks[$name]) AND self::$marks[$name][0]['stop'] === FALSE)
throw new Kohana_Exception('A benchmark named :name is already running.', array(':name' => $name));
if ( ! isset(self::$marks[$name]))
{
self::$marks[$name] = array();
}
$mark = array
(
'start' => microtime(TRUE),
'stop' => FALSE,
'memory_start' => self::memory_usage(),
'memory_stop' => FALSE
);
array_unshift(self::$marks[$name], $mark);
}
/**
* Set a benchmark stop point.
*
* @param string benchmark name
* @return void
*/
public static function stop($name)
{
if (isset(self::$marks[$name]) AND self::$marks[$name][0]['stop'] === FALSE)
{
self::$marks[$name][0]['stop'] = microtime(TRUE);
self::$marks[$name][0]['memory_stop'] = self::memory_usage();
}
}
/**
* Get the elapsed time between a start and stop.
*
* @param string benchmark name, TRUE for all
* @param integer number of decimal places to count to
* @return array
*/
public static function get($name, $decimals = 4)
{
if ($name === TRUE)
{
$times = array();
$names = array_keys(self::$marks);
foreach ($names as $name)
{
// Get each mark recursively
$times[$name] = self::get($name, $decimals);
}
// Return the array
return $times;
}
if ( ! isset(self::$marks[$name]))
return FALSE;
if (self::$marks[$name][0]['stop'] === FALSE)
{
// Stop the benchmark to prevent mis-matched results
self::stop($name);
}
// Return a string version of the time between the start and stop points
// Properly reading a float requires using number_format or sprintf
$time = $memory = 0;
for ($i = 0; $i < count(self::$marks[$name]); $i++)
{
$time += self::$marks[$name][$i]['stop'] - self::$marks[$name][$i]['start'];
$memory += self::$marks[$name][$i]['memory_stop'] - self::$marks[$name][$i]['memory_start'];
}
return array
(
'time' => number_format($time, $decimals),
'memory' => $memory,
'count' => count(self::$marks[$name])
);
}
/**
* Returns the current memory usage. This is only possible if the
* memory_get_usage function is supported in PHP.
*
* @return integer
*/
private static function memory_usage()
{
static $func;
if ($func === NULL)
{
// Test if memory usage can be seen
$func = function_exists('memory_get_usage');
}
return $func ? memory_get_usage() : 0;
}
} // End Benchmark

View File

@ -0,0 +1,233 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Process queuing/execution class. Allows an unlimited number of callbacks
* to be added to 'events'. Events can be run multiple times, and can also
* process event-specific data. By default, Kohana has several system events.
*
* $Id: Event.php 4679 2009-11-10 01:45:52Z isaiah $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
* @link http://docs.kohanaphp.com/general/events
*/
abstract class Event_Core {
// Event callbacks
protected static $events = array();
// Cache of events that have been run
protected static $has_run = array();
// Data that can be processed during events
public static $data;
/**
* Add a callback to an event queue.
*
* @param string event name
* @param array http://php.net/callback
* @param boolean prevent duplicates
* @return boolean
*/
public static function add($name, $callback, $unique = FALSE)
{
if ( ! isset(Event::$events[$name]))
{
// Create an empty event if it is not yet defined
Event::$events[$name] = array();
}
elseif ($unique AND in_array($callback, Event::$events[$name], TRUE))
{
// The event already exists
return FALSE;
}
// Add the event
Event::$events[$name][] = $callback;
return TRUE;
}
/**
* Add a callback to an event queue, before a given event.
*
* @param string event name
* @param array existing event callback
* @param array event callback
* @return boolean
*/
public static function add_before($name, $existing, $callback)
{
if (empty(Event::$events[$name]) OR ($key = array_search($existing, Event::$events[$name])) === FALSE)
{
// Just add the event if there are no events
return Event::add($name, $callback);
}
else
{
// Insert the event immediately before the existing event
return Event::insert_event($name, $key, $callback);
}
}
/**
* Add a callback to an event queue, after a given event.
*
* @param string event name
* @param array existing event callback
* @param array event callback
* @return boolean
*/
public static function add_after($name, $existing, $callback)
{
if (empty(Event::$events[$name]) OR ($key = array_search($existing, Event::$events[$name])) === FALSE)
{
// Just add the event if there are no events
return Event::add($name, $callback);
}
else
{
// Insert the event immediately after the existing event
return Event::insert_event($name, $key + 1, $callback);
}
}
/**
* Inserts a new event at a specfic key location.
*
* @param string event name
* @param integer key to insert new event at
* @param array event callback
* @return void
*/
private static function insert_event($name, $key, $callback)
{
if (in_array($callback, Event::$events[$name], TRUE))
return FALSE;
// Add the new event at the given key location
Event::$events[$name] = array_merge
(
// Events before the key
array_slice(Event::$events[$name], 0, $key),
// New event callback
array($callback),
// Events after the key
array_slice(Event::$events[$name], $key)
);
return TRUE;
}
/**
* Replaces an event with another event.
*
* @param string event name
* @param array event to replace
* @param array new callback
* @return boolean
*/
public static function replace($name, $existing, $callback)
{
if (empty(Event::$events[$name]) OR ($key = array_search($existing, Event::$events[$name], TRUE)) === FALSE)
return FALSE;
if ( ! in_array($callback, Event::$events[$name], TRUE))
{
// Replace the exisiting event with the new event
Event::$events[$name][$key] = $callback;
}
else
{
// Remove the existing event from the queue
unset(Event::$events[$name][$key]);
// Reset the array so the keys are ordered properly
Event::$events[$name] = array_values(Event::$events[$name]);
}
return TRUE;
}
/**
* Get all callbacks for an event.
*
* @param string event name
* @return array
*/
public static function get($name)
{
return empty(Event::$events[$name]) ? array() : Event::$events[$name];
}
/**
* Clear some or all callbacks from an event.
*
* @param string event name
* @param array specific callback to remove, FALSE for all callbacks
* @return void
*/
public static function clear($name, $callback = FALSE)
{
if ($callback === FALSE)
{
Event::$events[$name] = array();
}
elseif (isset(Event::$events[$name]))
{
// Loop through each of the event callbacks and compare it to the
// callback requested for removal. The callback is removed if it
// matches.
foreach (Event::$events[$name] as $i => $event_callback)
{
if ($callback === $event_callback)
{
unset(Event::$events[$name][$i]);
}
}
}
}
/**
* Execute all of the callbacks attached to an event.
*
* @param string event name
* @param array data can be processed as Event::$data by the callbacks
* @return void
*/
public static function run($name, & $data = NULL)
{
if ( ! empty(Event::$events[$name]))
{
// So callbacks can access Event::$data
Event::$data =& $data;
$callbacks = Event::get($name);
foreach ($callbacks as $callback)
{
call_user_func_array($callback, array(&$data));
}
// Do this to prevent data from getting 'stuck'
$clear_data = '';
Event::$data =& $clear_data;
}
// The event has been run!
Event::$has_run[$name] = $name;
}
/**
* Check if a given event has been run.
*
* @param string event name
* @return boolean
*/
public static function has_run($name)
{
return isset(Event::$has_run[$name]);
}
} // End Event

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,331 @@
<?php defined('SYSPATH') or die('No direct script access.');
/**
* Provides a driver-based interface for setting and getting
* configuration options for the Kohana environment
*
* $Id: Kohana_Config.php 4679 2009-11-10 01:45:52Z isaiah $
*
* @package KohanaConfig
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class Kohana_Config_Core implements ArrayAccess {
/**
* The default Kohana_Config driver
* to use for system setup
*
* @var string
* @static
*/
public static $default_driver = 'array';
/**
* Kohana_Config instance
*
* @var array
* @static
*/
protected static $instance;
/**
* Returns a new instance of the Kohana_Config library
* based on the singleton pattern
*
* @param string driver
* @return Kohana_Config
* @access public
* @static
*/
public static function & instance()
{
// If the driver has not been initialised, intialise it
if ( empty(Kohana_Config::$instance))
{
//call a 1 time non singleton of Kohana_Config to get a list of drivers
$config = new Kohana_Config(array(
'config_drivers'=>array(
), 'internal_cache'=>FALSE
));
$core_config = $config->get('core');
Kohana_Config::$instance = new Kohana_Config($core_config);
}
// Return the Kohana_Config driver requested
return Kohana_Config::$instance;
}
/**
* The drivers for this object
*
* @var Kohana_Config_Driver
*/
protected $drivers;
/**
* Kohana_Config constructor to load the supplied driver.
* Enforces the singleton pattern.
*
* @param string driver
* @access protected
*/
protected function __construct(array $core_config)
{
$drivers = $core_config['config_drivers'];
//remove array if it's found in config
if (in_array('array', $drivers))
unset($drivers[array_search('array', $drivers)]);
//add array at the very end
$this->drivers = $drivers = array_merge($drivers, array(
'array'
));
foreach ($this->drivers as & $driver)
{
// Create the driver name
$driver = 'Config_'.ucfirst($driver).'_Driver';
// Ensure the driver loads correctly
if (!Kohana::auto_load($driver))
throw new Kohana_Exception('The :driver: driver for the :library: library could not be found.', array(
':driver:' => $driver, ':library:' => get_class($this)
));
// Load the new driver
$driver = new $driver($core_config);
// Ensure the new driver is valid
if (!$driver instanceof Config_Driver)
throw new Kohana_Exception('The :driver: driver for the :library: library must implement the :interface: interface', array(
':driver:' => $driver, ':library:' => get_class($this), ':interface:' => 'Config_Driver'
));
}
}
/**
* Gets a value from the configuration driver
*
* @param string key
* @param bool slash
* @param bool required
* @return mixed
* @access public
*/
public function get($key, $slash = FALSE, $required = FALSE)
{
foreach ($this->drivers as $driver)
{
try
{
return $driver->get($key, $slash, $required);
}
catch (Kohana_Config_Exception $e)
{
//if it's the last driver in the list and it threw an exception, re throw it
if ($driver === $this->drivers[(count($this->drivers) - 1)])
throw $e;
}
}
}
/**
* Sets a value to the configuration drivers
*
* @param string key
* @param mixed value
* @return bool
* @access public
*/
public function set($key, $value)
{
foreach ($this->drivers as $driver)
{
try
{
$driver->set($key, $value);
}
catch (Kohana_Config_Exception $e)
{
//if it's the last driver in the list and it threw an exception, re throw it
if ($driver === $this->drivers[(count($this->drivers) - 1)])
throw $e;
}
}
return TRUE;
}
/**
* Clears a group from configuration
*
* @param string group
* @return bool
* @access public
*/
public function clear($group)
{
foreach ($this->drivers as $driver)
{
try
{
$driver->clear($group);
}
catch (Kohana_Config_Exception $e)
{
//if it's the last driver in the list and it threw an exception, re throw it
if ($driver === $this->drivers[(count($this->drivers) - 1)])
throw $e;
}
}
return TRUE;
}
/**
* Loads a configuration group
*
* @param string group
* @param bool required
* @return array
* @access public
*/
public function load($group, $required = FALSE)
{
foreach ($this->drivers as $driver)
{
try
{
return $driver->load($group, $required);
}
catch (Kohana_Config_Exception $e)
{
//if it's the last driver in the list and it threw an exception, re throw it
if ($driver === $this->drivers[(count($this->drivers) - 1)])
throw $e;
}
}
}
/**
* Returns true or false if any config has been loaded(either manually or from cache)
*
* @return boolean
*/
public function loaded()
{
return $this->drivers[(count($this->drivers) - 1)]->loaded;
}
/**
* The following allows access using
* array syntax.
*
* @example $config['core.site_domain']
*/
/**
* Allows access to configuration settings
* using the ArrayAccess interface
*
* @param string key
* @return mixed
* @access public
*/
public function offsetGet($key)
{
foreach ($this->drivers as $driver)
{
try
{
return $driver->get($key);
}
catch (Kohana_Config_Exception $e)
{
//if it's the last driver in the list and it threw an exception, re throw it
if ($driver === $this->drivers[(count($this->drivers) - 1)])
throw $e;
}
}
}
/**
* Allows access to configuration settings
* using the ArrayAccess interface
*
* @param string key
* @param mixed value
* @return bool
* @access public
*/
public function offsetSet($key, $value)
{
foreach ($this->drivers as $driver)
{
try
{
$driver->set($key, $value);
}
catch (Kohana_Config_Exception $e)
{
//if it's the last driver in the list and it threw an exception, re throw it
if ($driver === $this->drivers[(count($this->drivers) - 1)])
throw $e;
}
}
return TRUE;
}
/**
* Allows access to configuration settings
* using the ArrayAccess interface
*
* @param string key
* @return bool
* @access public
*/
public function offsetExists($key)
{
foreach ($this->drivers as $driver)
{
try
{
return $driver->setting_exists($key);
}
catch (Kohana_Config_Exception $e)
{
//if it's the last driver in the list and it threw an exception, re throw it
if ($driver === $this->drivers[(count($this->drivers) - 1)])
throw $e;
}
}
}
/**
* Allows access to configuration settings
* using the ArrayAccess interface
*
* @param string key
* @return bool
* @access public
*/
public function offsetUnset($key)
{
foreach ($this->drivers as $driver)
{
try
{
return $driver->set($key, NULL);
}
catch (Kohana_Config_Exception $e)
{
//if it's the last driver in the list and it threw an exception, re throw it
if ($driver === $this->drivers[(count($this->drivers) - 1)])
throw $e;
}
}
return TRUE;
}
} // End KohanaConfig
class Kohana_Config_Exception extends Kohana_Exception {}

View File

@ -0,0 +1,619 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Kohana Exceptions
*
* $Id: Kohana_Exception.php 4692 2009-12-04 15:59:44Z cbandy $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class Kohana_Exception_Core extends Exception {
public static $enabled = FALSE;
// Template file
public static $template = 'kohana/error';
// Show stack traces in errors
public static $trace_output = TRUE;
// Show source code in errors
public static $source_output = TRUE;
// To hold unique identifier to distinguish error output
protected $instance_identifier;
// Error code
protected $code = E_KOHANA;
/**
* Creates a new translated exception.
*
* @param string error message
* @param array translation variables
* @return void
*/
public function __construct($message, array $variables = NULL, $code = 0)
{
$this->instance_identifier = uniqid();
// Translate the error message
$message = __($message, $variables);
// Sets $this->message the proper way
parent::__construct($message, $code);
}
/**
* Enable Kohana exception handling.
*
* @uses Kohana_Exception::$template
* @return void
*/
public static function enable()
{
if ( ! Kohana_Exception::$enabled)
{
set_exception_handler(array('Kohana_Exception', 'handle'));
Kohana_Exception::$enabled = TRUE;
}
}
/**
* Disable Kohana exception handling.
*
* @return void
*/
public static function disable()
{
if (Kohana_Exception::$enabled)
{
restore_exception_handler();
Kohana_Exception::$enabled = FALSE;
}
}
/**
* Get a single line of text representing the exception:
*
* Error [ Code ]: Message ~ File [ Line ]
*
* @param object Exception
* @return string
*/
public static function text($e)
{
return sprintf('%s [ %s ]: %s ~ %s [ %d ]',
get_class($e), $e->getCode(), strip_tags($e->getMessage()), Kohana_Exception::debug_path($e->getFile()), $e->getLine());
}
/**
* exception handler, displays the error message, source of the
* exception, and the stack trace of the error.
*
* @uses Kohana::message()
* @uses Kohana_Exception::text()
* @param object exception object
* @return void
*/
public static function handle(Exception $e)
{
try
{
// Get the exception information
$type = get_class($e);
$code = $e->getCode();
$message = $e->getMessage();
// Create a text version of the exception
$error = Kohana_Exception::text($e);
// Add this exception to the log
Kohana_Log::add('error', $error);
// Manually save logs after exceptions
Kohana_Log::save();
if (Kohana::config('core.display_errors') === FALSE)
{
// Do not show the details
$file = $line = NULL;
$trace = array();
$template = '_disabled';
}
else
{
$file = $e->getFile();
$line = $e->getLine();
$trace = $e->getTrace();
$template = '';
}
if ($e instanceof Kohana_Exception)
{
$template = $e->getTemplate().$template;
if ( ! headers_sent())
{
$e->sendHeaders();
}
// Use the human-readable error name
$code = Kohana::message('core.errors.'.$code);
}
else
{
$template = Kohana_Exception::$template.$template;
if ( ! headers_sent())
{
header('HTTP/1.1 500 Internal Server Error');
}
if ($e instanceof ErrorException)
{
// Use the human-readable error name
$code = Kohana::message('core.errors.'.$e->getSeverity());
if (version_compare(PHP_VERSION, '5.3', '<'))
{
// Workaround for a bug in ErrorException::getTrace() that exists in
// all PHP 5.2 versions. @see http://bugs.php.net/45895
for ($i = count($trace) - 1; $i > 0; --$i)
{
if (isset($trace[$i - 1]['args']))
{
// Re-position the arguments
$trace[$i]['args'] = $trace[$i - 1]['args'];
unset($trace[$i - 1]['args']);
}
}
}
}
}
// Clean the output buffer if one exists
ob_get_level() and ob_clean();
if ($template = Kohana::find_file('views', $template))
{
include $template;
}
}
catch (Exception $e)
{
// Clean the output buffer if one exists
ob_get_level() and ob_clean();
// Display the exception text
echo Kohana_Exception::text($e), "\n";
}
if (Kohana::$server_api === 'cli')
{
// Exit with an error status
exit(1);
}
}
/**
* Returns the template for this exception.
*
* @uses Kohana_Exception::$template
* @return string
*/
public function getTemplate()
{
return Kohana_Exception::$template;
}
/**
* Sends an Internal Server Error header.
*
* @return void
*/
public function sendHeaders()
{
// Send the 500 header
header('HTTP/1.1 500 Internal Server Error');
}
/**
* Returns an HTML string of information about a single variable.
*
* Borrows heavily on concepts from the Debug class of {@link http://nettephp.com/ Nette}.
*
* @param mixed variable to dump
* @param integer maximum length of strings
* @return string
*/
public static function dump($value, $length = 128)
{
return Kohana_Exception::_dump($value, $length);
}
/**
* Helper for Kohana_Exception::dump(), handles recursion in arrays and objects.
*
* @param mixed variable to dump
* @param integer maximum length of strings
* @param integer recursion level (internal)
* @return string
*/
private static function _dump( & $var, $length = 128, $level = 0)
{
if ($var === NULL)
{
return '<small>NULL</small>';
}
elseif (is_bool($var))
{
return '<small>bool</small> '.($var ? 'TRUE' : 'FALSE');
}
elseif (is_float($var))
{
return '<small>float</small> '.$var;
}
elseif (is_resource($var))
{
if (($type = get_resource_type($var)) === 'stream' AND $meta = stream_get_meta_data($var))
{
$meta = stream_get_meta_data($var);
if (isset($meta['uri']))
{
$file = $meta['uri'];
if (function_exists('stream_is_local'))
{
// Only exists on PHP >= 5.2.4
if (stream_is_local($file))
{
$file = Kohana_Exception::debug_path($file);
}
}
return '<small>resource</small><span>('.$type.')</span> '.htmlspecialchars($file, ENT_NOQUOTES, Kohana::CHARSET);
}
}
else
{
return '<small>resource</small><span>('.$type.')</span>';
}
}
elseif (is_string($var))
{
if (strlen($var) > $length)
{
// Encode the truncated string
$str = htmlspecialchars(substr($var, 0, $length), ENT_NOQUOTES, Kohana::CHARSET).'&nbsp;&hellip;';
}
else
{
// Encode the string
$str = htmlspecialchars($var, ENT_NOQUOTES, Kohana::CHARSET);
}
return '<small>string</small><span>('.strlen($var).')</span> "'.$str.'"';
}
elseif (is_array($var))
{
$output = array();
// Indentation for this variable
$space = str_repeat($s = ' ', $level);
static $marker;
if ($marker === NULL)
{
// Make a unique marker
$marker = uniqid("\x00");
}
if (empty($var))
{
// Do nothing
}
elseif (isset($var[$marker]))
{
$output[] = "(\n$space$s*RECURSION*\n$space)";
}
elseif ($level < 5)
{
$output[] = "<span>(";
$var[$marker] = TRUE;
foreach ($var as $key => & $val)
{
if ($key === $marker) continue;
if ( ! is_int($key))
{
$key = '"'.$key.'"';
}
$output[] = "$space$s$key => ".Kohana_Exception::_dump($val, $length, $level + 1);
}
unset($var[$marker]);
$output[] = "$space)</span>";
}
else
{
// Depth too great
$output[] = "(\n$space$s...\n$space)";
}
return '<small>array</small><span>('.count($var).')</span> '.implode("\n", $output);
}
elseif (is_object($var))
{
// Copy the object as an array
$array = (array) $var;
$output = array();
// Indentation for this variable
$space = str_repeat($s = ' ', $level);
$hash = spl_object_hash($var);
// Objects that are being dumped
static $objects = array();
if (empty($var))
{
// Do nothing
}
elseif (isset($objects[$hash]))
{
$output[] = "{\n$space$s*RECURSION*\n$space}";
}
elseif ($level < 5)
{
$output[] = "<code>{";
$objects[$hash] = TRUE;
foreach ($array as $key => & $val)
{
if ($key[0] === "\x00")
{
// Determine if the access is private or protected
$access = '<small>'.($key[1] === '*' ? 'protected' : 'private').'</small>';
// Remove the access level from the variable name
$key = substr($key, strrpos($key, "\x00") + 1);
}
else
{
$access = '<small>public</small>';
}
$output[] = "$space$s$access $key => ".Kohana_Exception::_dump($val, $length, $level + 1);
}
unset($objects[$hash]);
$output[] = "$space}</code>";
}
else
{
// Depth too great
$output[] = "{\n$space$s...\n$space}";
}
return '<small>object</small> <span>'.get_class($var).'('.count($array).')</span> '.implode("\n", $output);
}
else
{
return '<small>'.gettype($var).'</small> '.htmlspecialchars(print_r($var, TRUE), ENT_NOQUOTES, Kohana::CHARSET);
}
}
/**
* Removes APPPATH, SYSPATH, MODPATH, and DOCROOT from filenames, replacing
* them with the plain text equivalents.
*
* @param string path to sanitize
* @return string
*/
public static function debug_path($file)
{
if (strpos($file, APPPATH) === 0)
{
$file = 'APPPATH/'.substr($file, strlen(APPPATH));
}
elseif (strpos($file, SYSPATH) === 0)
{
$file = 'SYSPATH/'.substr($file, strlen(SYSPATH));
}
elseif (strpos($file, MODPATH) === 0)
{
$file = 'MODPATH/'.substr($file, strlen(MODPATH));
}
elseif (strpos($file, DOCROOT) === 0)
{
$file = 'DOCROOT/'.substr($file, strlen(DOCROOT));
}
return $file;
}
/**
* Returns an array of lines from a file.
*
* // Returns the current line of the current file
* echo Kohana_Exception::debug_source(__FILE__, __LINE__);
*
* @param string file to open
* @param integer line number to find
* @param integer number of padding lines
* @return array
*/
public static function debug_source($file, $line_number, $padding = 5)
{
// Make sure we can read the source file
if ( ! is_readable($file))
return array();
// Open the file and set the line position
$file = fopen($file, 'r');
$line = 0;
// Set the reading range
$range = array('start' => $line_number - $padding, 'end' => $line_number + $padding);
// Set the zero-padding amount for line numbers
$format = '% '.strlen($range['end']).'d';
$source = array();
while (($row = fgets($file)) !== FALSE)
{
// Increment the line number
if (++$line > $range['end'])
break;
if ($line >= $range['start'])
{
$source[sprintf($format, $line)] = $row;
}
}
// Close the file
fclose($file);
return $source;
}
/**
* Returns an array of strings that represent each step in the backtrace.
*
* @param array trace to analyze
* @return array
*/
public static function trace($trace = NULL)
{
if ($trace === NULL)
{
// Start a new trace
$trace = debug_backtrace();
}
// Non-standard function calls
$statements = array('include', 'include_once', 'require', 'require_once');
$output = array();
foreach ($trace as $step)
{
if ( ! isset($step['function']))
{
// Invalid trace step
continue;
}
if (isset($step['file']) AND isset($step['line']))
{
// Include the source of this step
$source = Kohana_Exception::debug_source($step['file'], $step['line']);
}
if (isset($step['file']))
{
$file = $step['file'];
if (isset($step['line']))
{
$line = $step['line'];
}
}
// function()
$function = $step['function'];
if (in_array($step['function'], $statements))
{
if (empty($step['args']))
{
// No arguments
$args = array();
}
else
{
// Sanitize the file path
$args = array($step['args'][0]);
}
}
elseif (isset($step['args']))
{
if ($step['function'] === '{closure}')
{
// Introspection on closures in a stack trace is impossible
$params = NULL;
}
else
{
if (isset($step['class']))
{
if (method_exists($step['class'], $step['function']))
{
$reflection = new ReflectionMethod($step['class'], $step['function']);
}
else
{
$reflection = new ReflectionMethod($step['class'], '__call');
}
}
else
{
$reflection = new ReflectionFunction($step['function']);
}
// Get the function parameters
$params = $reflection->getParameters();
}
$args = array();
foreach ($step['args'] as $i => $arg)
{
if (isset($params[$i]))
{
// Assign the argument by the parameter name
$args[$params[$i]->name] = $arg;
}
else
{
// Assign the argument by number
$args[$i] = $arg;
}
}
}
if (isset($step['class']))
{
// Class->method() or Class::method()
$function = $step['class'].$step['type'].$step['function'];
}
$output[] = array(
'function' => $function,
'args' => isset($args) ? $args : NULL,
'file' => isset($file) ? $file : NULL,
'line' => isset($line) ? $line : NULL,
'source' => isset($source) ? $source : NULL,
);
unset($function, $args, $file, $line, $source);
}
return $output;
}
} // End Kohana Exception

View File

@ -0,0 +1,275 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Array helper class.
*
* $Id: arr.php 4680 2009-11-10 01:57:00Z isaiah $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class arr_Core {
/**
* Return a callback array from a string, eg: limit[10,20] would become
* array('limit', array('10', '20'))
*
* @param string callback string
* @return array
*/
public static function callback_string($str)
{
// command[param,param]
if (preg_match('/([^\[]*+)\[(.+)\]/', (string) $str, $match))
{
// command
$command = $match[1];
// param,param
$params = preg_split('/(?<!\\\\),/', $match[2]);
$params = str_replace('\,', ',', $params);
}
else
{
// command
$command = $str;
// No params
$params = NULL;
}
return array($command, $params);
}
/**
* Rotates a 2D array clockwise.
* Example, turns a 2x3 array into a 3x2 array.
*
* @param array array to rotate
* @param boolean keep the keys in the final rotated array. the sub arrays of the source array need to have the same key values.
* if your subkeys might not match, you need to pass FALSE here!
* @return array
*/
public static function rotate($source_array, $keep_keys = TRUE)
{
$new_array = array();
foreach ($source_array as $key => $value)
{
$value = ($keep_keys === TRUE) ? $value : array_values($value);
foreach ($value as $k => $v)
{
$new_array[$k][$key] = $v;
}
}
return $new_array;
}
/**
* Removes a key from an array and returns the value.
*
* @param string key to return
* @param array array to work on
* @return mixed value of the requested array key
*/
public static function remove($key, & $array)
{
if ( ! array_key_exists($key, $array))
return NULL;
$val = $array[$key];
unset($array[$key]);
return $val;
}
/**
* Extract one or more keys from an array. Each key given after the first
* argument (the array) will be extracted. Keys that do not exist in the
* search array will be NULL in the extracted data.
*
* @param array array to search
* @param string key name
* @return array
*/
public static function extract(array $search, $keys)
{
// Get the keys, removing the $search array
$keys = array_slice(func_get_args(), 1);
$found = array();
foreach ($keys as $key)
{
$found[$key] = isset($search[$key]) ? $search[$key] : NULL;
}
return $found;
}
/**
* Get the value of array[key]. If it doesn't exist, return default.
*
* @param array array to search
* @param string key name
* @param mixed default value
* @return mixed
*/
public static function get(array $array, $key, $default = NULL)
{
return isset($array[$key]) ? $array[$key] : $default;
}
/**
* Because PHP does not have this function.
*
* @param array array to unshift
* @param string key to unshift
* @param mixed value to unshift
* @return array
*/
public static function unshift_assoc( array & $array, $key, $val)
{
$array = array_reverse($array, TRUE);
$array[$key] = $val;
$array = array_reverse($array, TRUE);
return $array;
}
/**
* Because PHP does not have this function, and array_walk_recursive creates
* references in arrays and is not truly recursive.
*
* @param mixed callback to apply to each member of the array
* @param array array to map to
* @return array
*/
public static function map_recursive($callback, array $array)
{
foreach ($array as $key => $val)
{
// Map the callback to the key
$array[$key] = is_array($val) ? arr::map_recursive($callback, $val) : call_user_func($callback, $val);
}
return $array;
}
/**
* Emulates array_merge_recursive, but appends numeric keys and replaces
* associative keys, instead of appending all keys.
*
* @param array any number of arrays
* @return array
*/
public static function merge()
{
$total = func_num_args();
$result = array();
for ($i = 0; $i < $total; $i++)
{
foreach (func_get_arg($i) as $key => $val)
{
if (isset($result[$key]))
{
if (is_array($val))
{
// Arrays are merged recursively
$result[$key] = arr::merge($result[$key], $val);
}
elseif (is_int($key))
{
// Indexed arrays are appended
array_push($result, $val);
}
else
{
// Associative arrays are replaced
$result[$key] = $val;
}
}
else
{
// New values are added
$result[$key] = $val;
}
}
}
return $result;
}
/**
* Overwrites an array with values from input array(s).
* Non-existing keys will not be appended!
*
* @param array key array
* @param array input array(s) that will overwrite key array values
* @return array
*/
public static function overwrite($array1, $array2)
{
foreach (array_intersect_key($array2, $array1) as $key => $value)
{
$array1[$key] = $value;
}
if (func_num_args() > 2)
{
foreach (array_slice(func_get_args(), 2) as $array2)
{
foreach (array_intersect_key($array2, $array1) as $key => $value)
{
$array1[$key] = $value;
}
}
}
return $array1;
}
/**
* Recursively convert an array to an object.
*
* @param array array to convert
* @return object
*/
public static function to_object(array $array, $class = 'stdClass')
{
$object = new $class;
foreach ($array as $key => $value)
{
if (is_array($value))
{
// Convert the array to an object
$value = arr::to_object($value, $class);
}
// Add the value to the object
$object->{$key} = $value;
}
return $object;
}
/**
* Returns specific key/column from an array of objects.
*
* @param string|integer $key The key or column number to pluck from each object.
* @param array $array The array of objects to pluck from.
* @return array
*/
public static function pluck($key, $array)
{
$result = array();
foreach ($array as $i => $object)
{
$result[$i] = isset($object[$key]) ? $object[$key] : NULL;
}
return $result;
}
} // End arr

View File

@ -0,0 +1,151 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Cookie helper class.
*
* $Id: cookie.php 4679 2009-11-10 01:45:52Z isaiah $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class cookie_Core {
/**
* Sets a cookie with the given parameters.
*
* @param string cookie name or array of config options
* @param string cookie value
* @param integer number of seconds before the cookie expires
* @param string URL path to allow
* @param string URL domain to allow
* @param boolean HTTPS only
* @param boolean HTTP only (requires PHP 5.2 or higher)
* @return boolean
*/
public static function set($name, $value = NULL, $expire = NULL, $path = NULL, $domain = NULL, $secure = NULL, $httponly = NULL)
{
if (headers_sent())
return FALSE;
// If the name param is an array, we import it
is_array($name) and extract($name, EXTR_OVERWRITE);
// Fetch default options
$config = Kohana::config('cookie');
foreach (array('value', 'expire', 'domain', 'path', 'secure', 'httponly') as $item)
{
if ($$item === NULL AND isset($config[$item]))
{
$$item = $config[$item];
}
}
if ($expire !== 0)
{
// The expiration is expected to be a UNIX timestamp
$expire += time();
}
$value = cookie::salt($name, $value).'~'.$value;
return setcookie($name, $value, $expire, $path, $domain, $secure, $httponly);
}
/**
* Fetch a cookie value, using the Input library.
*
* @param string cookie name
* @param mixed default value
* @param boolean use XSS cleaning on the value
* @return string
*/
public static function get($name = NULL, $default = NULL, $xss_clean = FALSE)
{
// Return an array of all the cookies if we don't have a name
if ($name === NULL)
{
$cookies = array();
foreach($_COOKIE AS $key => $value)
{
$cookies[$key] = cookie::get($key, $default, $xss_clean);
}
return $cookies;
}
if ( ! isset($_COOKIE[$name]))
{
return $default;
}
// Get the cookie value
$cookie = $_COOKIE[$name];
// Find the position of the split between salt and contents
$split = strlen(cookie::salt($name, NULL));
if (isset($cookie[$split]) AND $cookie[$split] === '~')
{
// Separate the salt and the value
list ($hash, $value) = explode('~', $cookie, 2);
if (cookie::salt($name, $value) === $hash)
{
if ($xss_clean === TRUE AND Kohana::config('core.global_xss_filtering') === FALSE)
{
return Input::instance()->xss_clean($value);
}
// Cookie signature is valid
return $value;
}
// The cookie signature is invalid, delete it
cookie::delete($name);
}
return $default;
}
/**
* Nullify and unset a cookie.
*
* @param string cookie name
* @param string URL path
* @param string URL domain
* @return boolean
*/
public static function delete($name, $path = NULL, $domain = NULL)
{
// Delete the cookie from globals
unset($_COOKIE[$name]);
// Sets the cookie value to an empty string, and the expiration to 24 hours ago
return cookie::set($name, '', -86400, $path, $domain, FALSE, FALSE);
}
/**
* Generates a salt string for a cookie based on the name and value.
*
* @param string $name name of cookie
* @param string $value value of cookie
* @return string sha1 hash
*/
public static function salt($name, $value)
{
// Determine the user agent
$agent = isset($_SERVER['HTTP_USER_AGENT']) ? strtolower($_SERVER['HTTP_USER_AGENT']) : 'unknown';
// Cookie salt.
$salt = Kohana::config('cookie.salt');
return sha1($agent.$name.$value.$salt);
}
final private function __construct()
{
// Static class.
}
} // End cookie

View File

@ -0,0 +1,397 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Date helper class.
*
* $Id: date.php 4679 2009-11-10 01:45:52Z isaiah $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class date_Core {
/**
* Converts a UNIX timestamp to DOS format.
*
* @param integer UNIX timestamp
* @return integer
*/
public static function unix2dos($timestamp = FALSE)
{
$timestamp = ($timestamp === FALSE) ? getdate() : getdate($timestamp);
if ($timestamp['year'] < 1980)
{
return (1 << 21 | 1 << 16);
}
$timestamp['year'] -= 1980;
// What voodoo is this? I have no idea... Geert can explain it though,
// and that's good enough for me.
return ($timestamp['year'] << 25 | $timestamp['mon'] << 21 |
$timestamp['mday'] << 16 | $timestamp['hours'] << 11 |
$timestamp['minutes'] << 5 | $timestamp['seconds'] >> 1);
}
/**
* Converts a DOS timestamp to UNIX format.
*
* @param integer DOS timestamp
* @return integer
*/
public static function dos2unix($timestamp = FALSE)
{
$sec = 2 * ($timestamp & 0x1f);
$min = ($timestamp >> 5) & 0x3f;
$hrs = ($timestamp >> 11) & 0x1f;
$day = ($timestamp >> 16) & 0x1f;
$mon = ($timestamp >> 21) & 0x0f;
$year = ($timestamp >> 25) & 0x7f;
return mktime($hrs, $min, $sec, $mon, $day, $year + 1980);
}
/**
* Returns the offset (in seconds) between two time zones.
* @see http://php.net/timezones
*
* @param string timezone to find the offset of
* @param string|boolean timezone used as the baseline
* @param string time at which to calculate
* @return integer
*/
public static function offset($remote, $local = TRUE, $when = 'now')
{
if ($local === TRUE)
{
$local = date_default_timezone_get();
}
// Create timezone objects
$remote = new DateTimeZone($remote);
$local = new DateTimeZone($local);
// Create date objects from timezones
$time_there = new DateTime($when, $remote);
$time_here = new DateTime($when, $local);
// Find the offset
return $remote->getOffset($time_there) - $local->getOffset($time_here);
}
/**
* Number of seconds in a minute, incrementing by a step.
*
* @param integer amount to increment each step by, 1 to 30
* @param integer start value
* @param integer end value
* @return array A mirrored (foo => foo) array from 1-60.
*/
public static function seconds($step = 1, $start = 0, $end = 60)
{
// Always integer
$step = (int) $step;
$seconds = array();
for ($i = $start; $i < $end; $i += $step)
{
$seconds[$i] = ($i < 10) ? '0'.$i : $i;
}
return $seconds;
}
/**
* Number of minutes in an hour, incrementing by a step.
*
* @param integer amount to increment each step by, 1 to 30
* @return array A mirrored (foo => foo) array from 1-60.
*/
public static function minutes($step = 5)
{
// Because there are the same number of minutes as seconds in this set,
// we choose to re-use seconds(), rather than creating an entirely new
// function. Shhhh, it's cheating! ;) There are several more of these
// in the following methods.
return date::seconds($step);
}
/**
* Number of hours in a day.
*
* @param integer amount to increment each step by
* @param boolean use 24-hour time
* @param integer the hour to start at
* @return array A mirrored (foo => foo) array from start-12 or start-23.
*/
public static function hours($step = 1, $long = FALSE, $start = NULL)
{
// Default values
$step = (int) $step;
$long = (bool) $long;
$hours = array();
// Set the default start if none was specified.
if ($start === NULL)
{
$start = ($long === FALSE) ? 1 : 0;
}
$hours = array();
// 24-hour time has 24 hours, instead of 12
$size = ($long === TRUE) ? 23 : 12;
for ($i = $start; $i <= $size; $i += $step)
{
$hours[$i] = $i;
}
return $hours;
}
/**
* Returns AM or PM, based on a given hour.
*
* @param integer number of the hour
* @return string
*/
public static function ampm($hour)
{
// Always integer
$hour = (int) $hour;
return ($hour > 11) ? 'PM' : 'AM';
}
/**
* Adjusts a non-24-hour number into a 24-hour number.
*
* @param integer hour to adjust
* @param string AM or PM
* @return string
*/
public static function adjust($hour, $ampm)
{
$hour = (int) $hour;
$ampm = strtolower($ampm);
switch ($ampm)
{
case 'am':
if ($hour == 12)
$hour = 0;
break;
case 'pm':
if ($hour < 12)
$hour += 12;
break;
}
return sprintf('%02s', $hour);
}
/**
* Number of days in month.
*
* @param integer number of month
* @param integer number of year to check month, defaults to the current year
* @return array A mirrored (foo => foo) array of the days.
*/
public static function days($month, $year = FALSE)
{
static $months;
// Always integers
$month = (int) $month;
$year = (int) $year;
// Use the current year by default
$year = ($year == FALSE) ? date('Y') : $year;
// We use caching for months, because time functions are used
if (empty($months[$year][$month]))
{
$months[$year][$month] = array();
// Use date to find the number of days in the given month
$total = date('t', mktime(1, 0, 0, $month, 1, $year)) + 1;
for ($i = 1; $i < $total; $i++)
{
$months[$year][$month][$i] = $i;
}
}
return $months[$year][$month];
}
/**
* Number of months in a year
*
* @return array A mirrored (foo => foo) array from 1-12.
*/
public static function months()
{
return date::hours();
}
/**
* Returns an array of years between a starting and ending year.
* Uses the current year +/- 5 as the max/min.
*
* @param integer starting year
* @param integer ending year
* @return array
*/
public static function years($start = FALSE, $end = FALSE)
{
// Default values
$start = ($start === FALSE) ? date('Y') - 5 : (int) $start;
$end = ($end === FALSE) ? date('Y') + 5 : (int) $end;
$years = array();
// Add one, so that "less than" works
$end += 1;
for ($i = $start; $i < $end; $i++)
{
$years[$i] = $i;
}
return $years;
}
/**
* Returns time difference between two timestamps, in human readable format.
*
* @param integer timestamp
* @param integer timestamp, defaults to the current time
* @param string formatting string
* @return string|array
*/
public static function timespan($time1, $time2 = NULL, $output = 'years,months,weeks,days,hours,minutes,seconds')
{
// Array with the output formats
$output = preg_split('/[^a-z]+/', strtolower((string) $output));
// Invalid output
if (empty($output))
return FALSE;
// Make the output values into keys
extract(array_flip($output), EXTR_SKIP);
// Default values
$time1 = max(0, (int) $time1);
$time2 = empty($time2) ? time() : max(0, (int) $time2);
// Calculate timespan (seconds)
$timespan = abs($time1 - $time2);
// All values found using Google Calculator.
// Years and months do not match the formula exactly, due to leap years.
// Years ago, 60 * 60 * 24 * 365
isset($years) and $timespan -= 31556926 * ($years = (int) floor($timespan / 31556926));
// Months ago, 60 * 60 * 24 * 30
isset($months) and $timespan -= 2629744 * ($months = (int) floor($timespan / 2629743.83));
// Weeks ago, 60 * 60 * 24 * 7
isset($weeks) and $timespan -= 604800 * ($weeks = (int) floor($timespan / 604800));
// Days ago, 60 * 60 * 24
isset($days) and $timespan -= 86400 * ($days = (int) floor($timespan / 86400));
// Hours ago, 60 * 60
isset($hours) and $timespan -= 3600 * ($hours = (int) floor($timespan / 3600));
// Minutes ago, 60
isset($minutes) and $timespan -= 60 * ($minutes = (int) floor($timespan / 60));
// Seconds ago, 1
isset($seconds) and $seconds = $timespan;
// Remove the variables that cannot be accessed
unset($timespan, $time1, $time2);
// Deny access to these variables
$deny = array_flip(array('deny', 'key', 'difference', 'output'));
// Return the difference
$difference = array();
foreach ($output as $key)
{
if (isset($$key) AND ! isset($deny[$key]))
{
// Add requested key to the output
$difference[$key] = $$key;
}
}
// Invalid output formats string
if (empty($difference))
return FALSE;
// If only one output format was asked, don't put it in an array
if (count($difference) === 1)
return current($difference);
// Return array
return $difference;
}
/**
* Returns time difference between two timestamps, in the format:
* N year, N months, N weeks, N days, N hours, N minutes, and N seconds ago
*
* @param integer timestamp
* @param integer timestamp, defaults to the current time
* @param string formatting string
* @return string
*/
public static function timespan_string($time1, $time2 = NULL, $output = 'years,months,weeks,days,hours,minutes,seconds')
{
if ($difference = date::timespan($time1, $time2, $output) AND is_array($difference))
{
// Determine the key of the last item in the array
$last = end($difference);
$last = key($difference);
$span = array();
foreach ($difference as $name => $amount)
{
if ($amount === 0)
{
// Skip empty amounts
continue;
}
// Add the amount to the span
$span[] = ($name === $last ? ' and ' : ', ').$amount.' '.($amount === 1 ? inflector::singular($name) : $name);
}
// If the difference is less than 60 seconds, remove the preceding and.
if (count($span) === 1)
{
$span[0] = ltrim($span[0], 'and ');
}
// Replace difference by making the span into a string
$difference = trim(implode('', $span), ',');
}
elseif (is_int($difference))
{
// Single-value return
$difference = $difference.' '.($difference === 1 ? inflector::singular($output) : $output);
}
return $difference;
}
} // End date

View File

@ -0,0 +1,49 @@
<?php defined('SYSPATH') or die('No direct script access.');
/**
* Database helper class.
*
* $Id: $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class db_Core {
public static function query($sql)
{
return new Database_Query($sql);
}
public static function build($database = 'default')
{
return new Database_Builder($database);
}
public static function select($columns = NULL)
{
return db::build()->select($columns);
}
public static function insert($table = NULL, $set = NULL)
{
return db::build()->insert($table, $set);
}
public static function update($table = NULL, $set = NULL, $where = NULL)
{
return db::build()->update($table, $set, $where);
}
public static function delete($table = NULL, $where = NULL)
{
return db::build()->delete($table, $where);
}
public static function expr($expression)
{
return new Database_Expression($expression);
}
} // End db

View File

@ -0,0 +1,137 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Download helper class.
*
* $Id: download.php 4679 2009-11-10 01:45:52Z isaiah $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class download_Core {
/**
* Send headers necessary to invoke a "Save As" dialog
*
* @link http://support.microsoft.com/kb/260519
* @link http://greenbytes.de/tech/tc2231/
*
* @param string file name
* @return string file name as it was sent
*/
public static function dialog($filename)
{
$filename = basename($filename);
header('Content-Disposition: attachment; filename="'.$filename.'"');
return $filename;
}
/**
* Send the contents of a file or a data string with the proper MIME type and exit.
*
* @uses exit()
* @uses Kohana::close_buffers()
*
* @param string a file path or file name
* @param string optional data to send
* @return void
*/
public static function send($filename, $data = NULL)
{
if ($data === NULL)
{
$filepath = realpath($filename);
$filename = basename($filepath);
$filesize = filesize($filepath);
}
else
{
$filename = basename($filename);
$filesize = strlen($data);
}
// Retrieve MIME type by extension
$mime = Kohana::config('mimes.'.strtolower(substr(strrchr($filename, '.'), 1)));
$mime = empty($mime) ? 'application/octet-stream' : $mime[0];
// Close output buffers
Kohana::close_buffers(FALSE);
// Clear any output
Event::add('system.display', create_function('', 'Kohana::$output = "";'));
// Send headers
header("Content-Type: $mime");
header('Content-Length: '.sprintf('%d', $filesize));
header('Content-Transfer-Encoding: binary');
// Send data
if ($data === NULL)
{
$handle = fopen($filepath, 'rb');
fpassthru($handle);
fclose($handle);
}
else
{
echo $data;
}
exit;
}
/**
* Force the download of a file by the user's browser by preventing any
* caching. Contains a workaround for Internet Explorer.
*
* @link http://support.microsoft.com/kb/316431
* @link http://support.microsoft.com/kb/812935
*
* @uses download::dialog()
* @uses download::send()
*
* @param string a file path or file name
* @param mixed data to be sent if the filename does not exist
* @param string suggested filename to display in the download
* @return void
*/
public static function force($filename = NULL, $data = NULL, $nicename = NULL)
{
download::dialog(empty($nicename) ? $filename : $nicename);
// Prevent caching
header('Expires: Thu, 01 Jan 1970 00:00:00 GMT');
if (request::user_agent('browser') === 'Internet Explorer' AND request::user_agent('version') <= '6.0')
{
// HTTP 1.0
header('Pragma:');
// HTTP 1.1 with IE extensions
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
}
else
{
// HTTP 1.0
header('Pragma: no-cache');
// HTTP 1.1
header('Cache-Control: no-cache, max-age=0');
}
if (is_file($filename))
{
download::send($filename);
}
else
{
download::send($filename, $data);
}
}
} // End download

View File

@ -0,0 +1,120 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Controls headers that effect client caching of pages
*
* $Id: expires.php 4679 2009-11-10 01:45:52Z isaiah $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class expires_Core {
/**
* Sets the amount of time before content expires
*
* @param integer Seconds before the content expires
* @return integer Timestamp when the content expires
*/
public static function set($seconds = 60)
{
$now = time();
$expires = $now + $seconds;
header('Last-Modified: '.gmdate('D, d M Y H:i:s T', $now));
// HTTP 1.0
header('Expires: '.gmdate('D, d M Y H:i:s T', $expires));
// HTTP 1.1
header('Cache-Control: max-age='.$seconds);
return $expires;
}
/**
* Parses the If-Modified-Since header
*
* @return integer|boolean Timestamp or FALSE when header is lacking or malformed
*/
public static function get()
{
if ( ! empty($_SERVER['HTTP_IF_MODIFIED_SINCE']))
{
// Some versions of IE6 append "; length=####"
if (($strpos = strpos($_SERVER['HTTP_IF_MODIFIED_SINCE'], ';')) !== FALSE)
{
$mod_time = substr($_SERVER['HTTP_IF_MODIFIED_SINCE'], 0, $strpos);
}
else
{
$mod_time = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
}
return strtotime($mod_time);
}
return FALSE;
}
/**
* Checks to see if content should be updated otherwise sends Not Modified status
* and exits.
*
* @uses exit()
* @uses expires::get()
*
* @param integer Maximum age of the content in seconds
* @return integer|boolean Timestamp of the If-Modified-Since header or FALSE when header is lacking or malformed
*/
public static function check($seconds = 60)
{
if ($last_modified = expires::get())
{
$expires = $last_modified + $seconds;
$max_age = $expires - time();
if ($max_age > 0)
{
// Content has not expired
header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified');
header('Last-Modified: '.gmdate('D, d M Y H:i:s T', $last_modified));
// HTTP 1.0
header('Expires: '.gmdate('D, d M Y H:i:s T', $expires));
// HTTP 1.1
header('Cache-Control: max-age='.$max_age);
// Clear any output
Event::add('system.display', create_function('', 'Kohana::$output = "";'));
exit;
}
}
return $last_modified;
}
/**
* Check if expiration headers are already set
*
* @return boolean
*/
public static function headers_set()
{
foreach (headers_list() as $header)
{
if (strncasecmp($header, 'Expires:', 8) === 0
OR strncasecmp($header, 'Cache-Control:', 14) === 0
OR strncasecmp($header, 'Last-Modified:', 14) === 0)
{
return TRUE;
}
}
return FALSE;
}
} // End expires

View File

@ -0,0 +1,122 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Feed helper class.
*
* $Id: feed.php 4679 2009-11-10 01:45:52Z isaiah $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class feed_Core {
/**
* Parses a remote feed into an array.
*
* @param string remote feed URL
* @param integer item limit to fetch
* @return array
*/
public static function parse($feed, $limit = 0)
{
// Check if SimpleXML is installed
if( ! function_exists('simplexml_load_file'))
throw new Kohana_User_Exception('Feed Error', 'SimpleXML must be installed!');
// Make limit an integer
$limit = (int) $limit;
// Disable error reporting while opening the feed
$ER = error_reporting(0);
// Allow loading by filename or raw XML string
$load = (is_file($feed) OR valid::url($feed)) ? 'simplexml_load_file' : 'simplexml_load_string';
// Load the feed
$feed = $load($feed, 'SimpleXMLElement', LIBXML_NOCDATA);
// Restore error reporting
error_reporting($ER);
// Feed could not be loaded
if ($feed === FALSE)
return array();
// Detect the feed type. RSS 1.0/2.0 and Atom 1.0 are supported.
$feed = isset($feed->channel) ? $feed->xpath('//item') : $feed->entry;
$i = 0;
$items = array();
foreach ($feed as $item)
{
if ($limit > 0 AND $i++ === $limit)
break;
$items[] = (array) $item;
}
return $items;
}
/**
* Creates a feed from the given parameters.
*
* @param array feed information
* @param array items to add to the feed
* @param string define which format to use
* @param string define which encoding to use
* @return string
*/
public static function create($info, $items, $format = 'rss2', $encoding = 'UTF-8')
{
$info += array('title' => 'Generated Feed', 'link' => '', 'generator' => 'KohanaPHP');
$feed = '<?xml version="1.0" encoding="'.$encoding.'"?><rss version="2.0"><channel></channel></rss>';
$feed = simplexml_load_string($feed);
foreach ($info as $name => $value)
{
if (($name === 'pubDate' OR $name === 'lastBuildDate') AND (is_int($value) OR ctype_digit($value)))
{
// Convert timestamps to RFC 822 formatted dates
$value = date(DATE_RFC822, $value);
}
elseif (($name === 'link' OR $name === 'docs') AND strpos($value, '://') === FALSE)
{
// Convert URIs to URLs
$value = url::site($value, 'http');
}
// Add the info to the channel
$feed->channel->addChild($name, $value);
}
foreach ($items as $item)
{
// Add the item to the channel
$row = $feed->channel->addChild('item');
foreach ($item as $name => $value)
{
if ($name === 'pubDate' AND (is_int($value) OR ctype_digit($value)))
{
// Convert timestamps to RFC 822 formatted dates
$value = date(DATE_RFC822, $value);
}
elseif (($name === 'link' OR $name === 'guid') AND strpos($value, '://') === FALSE)
{
// Convert URIs to URLs
$value = url::site($value, 'http');
}
// Add the info to the row
$row->addChild($name, $value);
}
}
return $feed->asXML();
}
} // End feed

View File

@ -0,0 +1,186 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* File helper class.
*
* $Id: file.php 4679 2009-11-10 01:45:52Z isaiah $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class file_Core {
/**
* Attempt to get the mime type from a file. This method is horribly
* unreliable, due to PHP being horribly unreliable when it comes to
* determining the mime-type of a file.
*
* @param string filename
* @return string mime-type, if found
* @return boolean FALSE, if not found
*/
public static function mime($filename)
{
// Make sure the file is readable
if ( ! (is_file($filename) AND is_readable($filename)))
return FALSE;
// Get the extension from the filename
$extension = strtolower(substr(strrchr($filename, '.'), 1));
if (preg_match('/^(?:jpe?g|png|[gt]if|bmp|swf)$/', $extension))
{
// Disable error reporting
$ER = error_reporting(0);
// Use getimagesize() to find the mime type on images
$mime = getimagesize($filename);
// Turn error reporting back on
error_reporting($ER);
// Return the mime type
if (isset($mime['mime']))
return $mime['mime'];
}
if (function_exists('finfo_open'))
{
// Use the fileinfo extension
$finfo = finfo_open(FILEINFO_MIME);
$mime = finfo_file($finfo, $filename);
finfo_close($finfo);
// Return the mime type
return $mime;
}
if (ini_get('mime_magic.magicfile') AND function_exists('mime_content_type'))
{
// Return the mime type using mime_content_type
return mime_content_type($filename);
}
if ( ! KOHANA_IS_WIN)
{
// Attempt to locate use the file command, checking the return value
if ($command = trim(exec('which file', $output, $return)) AND $return === 0)
{
return trim(exec($command.' -bi '.escapeshellarg($filename)));
}
}
if ( ! empty($extension) AND is_array($mime = Kohana::config('mimes.'.$extension)))
{
// Return the mime-type guess, based on the extension
return $mime[0];
}
// Unable to find the mime-type
return FALSE;
}
/**
* Split a file into pieces matching a specific size.
*
* @param string file to be split
* @param string directory to output to, defaults to the same directory as the file
* @param integer size, in MB, for each chunk to be
* @return integer The number of pieces that were created.
*/
public static function split($filename, $output_dir = FALSE, $piece_size = 10)
{
// Find output dir
$output_dir = ($output_dir == FALSE) ? pathinfo(str_replace('\\', '/', realpath($filename)), PATHINFO_DIRNAME) : str_replace('\\', '/', realpath($output_dir));
$output_dir = rtrim($output_dir, '/').'/';
// Open files for writing
$input_file = fopen($filename, 'rb');
// Change the piece size to bytes
$piece_size = 1024 * 1024 * (int) $piece_size; // Size in bytes
// Set up reading variables
$read = 0; // Number of bytes read
$piece = 1; // Current piece
$chunk = 1024 * 8; // Chunk size to read
// Split the file
while ( ! feof($input_file))
{
// Open a new piece
$piece_name = $filename.'.'.str_pad($piece, 3, '0', STR_PAD_LEFT);
$piece_open = @fopen($piece_name, 'wb+') or die('Could not write piece '.$piece_name);
// Fill the current piece
while ($read < $piece_size AND $data = fread($input_file, $chunk))
{
fwrite($piece_open, $data) or die('Could not write to open piece '.$piece_name);
$read += $chunk;
}
// Close the current piece
fclose($piece_open);
// Prepare to open a new piece
$read = 0;
$piece++;
// Make sure that piece is valid
($piece < 999) or die('Maximum of 999 pieces exceeded, try a larger piece size');
}
// Close input file
fclose($input_file);
// Returns the number of pieces that were created
return ($piece - 1);
}
/**
* Join a split file into a whole file.
*
* @param string split filename, without .000 extension
* @param string output filename, if different then an the filename
* @return integer The number of pieces that were joined.
*/
public static function join($filename, $output = FALSE)
{
if ($output == FALSE)
$output = $filename;
// Set up reading variables
$piece = 1; // Current piece
$chunk = 1024 * 8; // Chunk size to read
// Open output file
$output_file = @fopen($output, 'wb+') or die('Could not open output file '.$output);
// Read each piece
while ($piece_open = @fopen(($piece_name = $filename.'.'.str_pad($piece, 3, '0', STR_PAD_LEFT)), 'rb'))
{
// Write the piece into the output file
while ( ! feof($piece_open))
{
fwrite($output_file, fread($piece_open, $chunk));
}
// Close the current piece
fclose($piece_open);
// Prepare for a new piece
$piece++;
// Make sure piece is valid
($piece < 999) or die('Maximum of 999 pieces exceeded');
}
// Close the output file
fclose($output_file);
// Return the number of pieces joined
return ($piece - 1);
}
} // End file

View File

@ -0,0 +1,468 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Form helper class.
*
* $Id: form.php 4699 2009-12-08 18:45:14Z isaiah $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class form_Core {
/**
* Generates an opening HTML form tag.
*
* @param string form action attribute
* @param array extra attributes
* @param array hidden fields to be created immediately after the form tag
* @param string non-default protocol, eg: https
* @return string
*/
public static function open($action = NULL, $attr = array(), $hidden = NULL, $protocol = NULL)
{
// Make sure that the method is always set
empty($attr['method']) and $attr['method'] = 'post';
if ($attr['method'] !== 'post' AND $attr['method'] !== 'get')
{
// If the method is invalid, use post
$attr['method'] = 'post';
}
if ($action === NULL)
{
// Use the current URL as the default action
$action = url::site(Router::$complete_uri, $protocol);
}
elseif (strpos($action, '://') === FALSE)
{
// Make the action URI into a URL
$action = url::site($action, $protocol);
}
// Set action
$attr['action'] = $action;
// Form opening tag
$form = '<form'.form::attributes($attr).'>'."\n";
// Add hidden fields immediate after opening tag
empty($hidden) or $form .= form::hidden($hidden);
return $form;
}
/**
* Generates an opening HTML form tag that can be used for uploading files.
*
* @param string form action attribute
* @param array extra attributes
* @param array hidden fields to be created immediately after the form tag
* @return string
*/
public static function open_multipart($action = NULL, $attr = array(), $hidden = array())
{
// Set multi-part form type
$attr['enctype'] = 'multipart/form-data';
return form::open($action, $attr, $hidden);
}
/**
* Creates a HTML form hidden input tag.
*
* @param string|array input name or an array of HTML attributes
* @param string input value, when using a name
* @param string a string to be attached to the end of the attributes
* @return string
*/
public static function hidden($data, $value = '', $extra = '')
{
if ( ! is_array($data))
{
$data = array('name' => $data);
}
$data['type'] = 'hidden';
return form::input($data, $value, $extra);
}
/**
* Creates an HTML form input tag. Defaults to a text type.
*
* @param string|array input name or an array of HTML attributes
* @param string input value, when using a name
* @param string a string to be attached to the end of the attributes
* @return string
*/
public static function input($data, $value = '', $extra = '')
{
if ( ! is_array($data))
{
$data = array('name' => $data);
}
// Type and value are required attributes
$data += array
(
'type' => 'text',
'value' => $value
);
return '<input'.form::attributes($data).' '.$extra.' />';
}
/**
* Creates a HTML form password input tag.
*
* @param string|array input name or an array of HTML attributes
* @param string input value, when using a name
* @param string a string to be attached to the end of the attributes
* @return string
*/
public static function password($data, $value = '', $extra = '')
{
if ( ! is_array($data))
{
$data = array('name' => $data);
}
$data['type'] = 'password';
return form::input($data, $value, $extra);
}
/**
* Creates an HTML form upload input tag.
*
* @param string|array input name or an array of HTML attributes
* @param string input value, when using a name
* @param string a string to be attached to the end of the attributes
* @return string
*/
public static function upload($data, $value = '', $extra = '')
{
if ( ! is_array($data))
{
$data = array('name' => $data);
}
$data['type'] = 'file';
return form::input($data, $value, $extra);
}
/**
* Creates an HTML form textarea tag.
*
* @param string|array input name or an array of HTML attributes
* @param string input value, when using a name
* @param string a string to be attached to the end of the attributes
* @param boolean encode existing entities
* @return string
*/
public static function textarea($data, $value = '', $extra = '', $double_encode = TRUE)
{
if ( ! is_array($data))
{
$data = array('name' => $data);
}
if ( ! isset($data['rows']))
{
$data['rows'] = '';
}
if ( ! isset($data['cols']))
{
$data['cols'] = '';
}
// Use the value from $data if possible, or use $value
$value = isset($data['value']) ? $data['value'] : $value;
// Value is not part of the attributes
unset($data['value']);
return '<textarea'.form::attributes($data, 'textarea').' '.$extra.'>'.htmlspecialchars($value, ENT_QUOTES, Kohana::CHARSET, $double_encode).'</textarea>';
}
/**
* Creates an HTML form select tag, or "dropdown menu".
*
* @param string|array input name or an array of HTML attributes
* @param array select options, when using a name
* @param string|array option key(s) that should be selected by default
* @param string a string to be attached to the end of the attributes
* @return string
*/
public static function dropdown($data, $options = NULL, $selected = NULL, $extra = '')
{
if ( ! is_array($data))
{
$data = array('name' => $data);
}
else
{
if (isset($data['options']))
{
// Use data options
$options = $data['options'];
}
if (isset($data['selected']))
{
// Use data selected
$selected = $data['selected'];
}
}
if (is_array($selected))
{
// Multi-select box
$data['multiple'] = 'multiple';
}
else
{
// Single selection (but converted to an array)
$selected = array($selected);
}
$input = '<select'.form::attributes($data, 'select').' '.$extra.'>'."\n";
foreach ((array) $options as $key => $val)
{
// Key should always be a string
$key = (string) $key;
if (is_array($val))
{
$input .= '<optgroup label="'.$key.'">'."\n";
foreach ($val as $inner_key => $inner_val)
{
// Inner key should always be a string
$inner_key = (string) $inner_key;
$sel = in_array($inner_key, $selected) ? ' selected="selected"' : '';
$input .= '<option value="'.$inner_key.'"'.$sel.'>'.htmlspecialchars($inner_val, ENT_QUOTES, Kohana::CHARSET).'</option>'."\n";
}
$input .= '</optgroup>'."\n";
}
else
{
$sel = in_array($key, $selected) ? ' selected="selected"' : '';
$input .= '<option value="'.$key.'"'.$sel.'>'.htmlspecialchars($val, ENT_QUOTES, Kohana::CHARSET).'</option>'."\n";
}
}
$input .= '</select>';
return $input;
}
/**
* Creates an HTML form checkbox input tag.
*
* @param string|array input name or an array of HTML attributes
* @param string input value, when using a name
* @param boolean make the checkbox checked by default
* @param string a string to be attached to the end of the attributes
* @return string
*/
public static function checkbox($data, $value = '', $checked = FALSE, $extra = '')
{
if ( ! is_array($data))
{
$data = array('name' => $data);
}
$data['type'] = 'checkbox';
if ($checked == TRUE OR (isset($data['checked']) AND $data['checked'] == TRUE))
{
$data['checked'] = 'checked';
}
else
{
unset($data['checked']);
}
return form::input($data, $value, $extra);
}
/**
* Creates an HTML form radio input tag.
*
* @param string|array input name or an array of HTML attributes
* @param string input value, when using a name
* @param boolean make the radio selected by default
* @param string a string to be attached to the end of the attributes
* @return string
*/
public static function radio($data = '', $value = '', $checked = FALSE, $extra = '')
{
if ( ! is_array($data))
{
$data = array('name' => $data);
}
$data['type'] = 'radio';
if ($checked == TRUE OR (isset($data['checked']) AND $data['checked'] == TRUE))
{
$data['checked'] = 'checked';
}
else
{
unset($data['checked']);
}
return form::input($data, $value, $extra);
}
/**
* Creates an HTML form submit input tag.
*
* @param string|array input name or an array of HTML attributes
* @param string input value, when using a name
* @param string a string to be attached to the end of the attributes
* @return string
*/
public static function submit($data = '', $value = '', $extra = '')
{
if ( ! is_array($data))
{
$data = array('name' => $data);
}
if (empty($data['name']))
{
// Remove the name if it is empty
unset($data['name']);
}
$data['type'] = 'submit';
return form::input($data, $value, $extra);
}
/**
* Creates an HTML form button input tag.
*
* @param string|array input name or an array of HTML attributes
* @param string input value, when using a name
* @param string a string to be attached to the end of the attributes
* @return string
*/
public static function button($data = '', $value = '', $extra = '')
{
if ( ! is_array($data))
{
$data = array('name' => $data);
}
if (empty($data['name']))
{
// Remove the name if it is empty
unset($data['name']);
}
if (isset($data['value']) AND empty($value))
{
$value = arr::remove('value', $data);
}
return '<button'.form::attributes($data, 'button').' '.$extra.'>'.$value.'</button>';
}
/**
* Creates an HTML form label tag.
*
* @param string|array label "for" name or an array of HTML attributes
* @param string label text or HTML
* @param string a string to be attached to the end of the attributes
* @return string
*/
public static function label($data = '', $text = NULL, $extra = '')
{
if ( ! is_array($data))
{
if (is_string($data))
{
// Specify the input this label is for
$data = array('for' => $data);
}
else
{
// No input specified
$data = array();
}
}
if ($text === NULL AND isset($data['for']))
{
// Make the text the human-readable input name
$text = ucwords(inflector::humanize($data['for']));
}
return '<label'.form::attributes($data).' '.$extra.'>'.$text.'</label>';
}
/**
* Sorts a key/value array of HTML attributes, putting form attributes first,
* and returns an attribute string.
*
* @param array HTML attributes array
* @return string
*/
public static function attributes($attr, $type = NULL)
{
if (empty($attr))
return '';
$order = array
(
'action',
'method',
'type',
'id',
'name',
'value',
'src',
'size',
'maxlength',
'rows',
'cols',
'accept',
'tabindex',
'accesskey',
'align',
'alt',
'title',
'class',
'style',
'selected',
'checked',
'readonly',
'disabled'
);
$sorted = array();
foreach ($order as $key)
{
if (isset($attr[$key]))
{
// Move the attribute to the sorted array
$sorted[$key] = $attr[$key];
// Remove the attribute from unsorted array
unset($attr[$key]);
}
}
// Combine the sorted and unsorted attributes and create an HTML string
return html::attributes(array_merge($sorted, $attr));
}
} // End form

View File

@ -0,0 +1,114 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Format helper class.
*
* $Id: format.php 4679 2009-11-10 01:45:52Z isaiah $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class format_Core {
/**
* Formats a number according to the current locale.
*
* @param float
* @param int|boolean number of fractional digits or TRUE to use the locale default
* @return string
*/
public static function number($number, $decimals = 0)
{
$locale = localeconv();
if ($decimals === TRUE)
return number_format($number, $locale['frac_digits'], $locale['decimal_point'], $locale['thousands_sep']);
return number_format($number, $decimals, $locale['decimal_point'], $locale['thousands_sep']);
}
/**
* Formats a phone number according to the specified format.
*
* @param string phone number
* @param string format string
* @return string
*/
public static function phone($number, $format = '3-3-4')
{
// Get rid of all non-digit characters in number string
$number_clean = preg_replace('/\D+/', '', (string) $number);
// Array of digits we need for a valid format
$format_parts = preg_split('/[^1-9][^0-9]*/', $format, -1, PREG_SPLIT_NO_EMPTY);
// Number must match digit count of a valid format
if (strlen($number_clean) !== array_sum($format_parts))
return $number;
// Build regex
$regex = '(\d{'.implode('})(\d{', $format_parts).'})';
// Build replace string
for ($i = 1, $c = count($format_parts); $i <= $c; $i++)
{
$format = preg_replace('/(?<!\$)[1-9][0-9]*/', '\$'.$i, $format, 1);
}
// Hocus pocus!
return preg_replace('/^'.$regex.'$/', $format, $number_clean);
}
/**
* Formats a URL to contain a protocol at the beginning.
*
* @param string possibly incomplete URL
* @return string
*/
public static function url($str = '')
{
// Clear protocol-only strings like "http://"
if ($str === '' OR substr($str, -3) === '://')
return '';
// If no protocol given, prepend "http://" by default
if (strpos($str, '://') === FALSE)
return 'http://'.$str;
// Return the original URL
return $str;
}
/**
* Normalizes a hexadecimal HTML color value. All values will be converted
* to lowercase, have a "#" prepended and contain six characters.
*
* @param string hexadecimal HTML color value
* @return string
*/
public static function color($str = '')
{
// Reject invalid values
if ( ! valid::color($str))
return '';
// Convert to lowercase
$str = strtolower($str);
// Prepend "#"
if ($str[0] !== '#')
{
$str = '#'.$str;
}
// Expand short notation
if (strlen($str) === 4)
{
$str = '#'.$str[1].$str[1].$str[2].$str[2].$str[3].$str[3];
}
return $str;
}
} // End format

View File

@ -0,0 +1,366 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* HTML helper class.
*
* $Id: html.php 4679 2009-11-10 01:45:52Z isaiah $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class html_Core {
// Enable or disable automatic setting of target="_blank"
public static $windowed_urls = FALSE;
/**
* Convert special characters to HTML entities
*
* @param string string to convert
* @param boolean encode existing entities
* @return string
*/
public static function chars($str, $double_encode = TRUE)
{
// Return HTML entities using the Kohana charset
return htmlspecialchars($str, ENT_QUOTES, Kohana::CHARSET, $double_encode);
}
/**
* Create HTML link anchors.
*
* @param string URL or URI string
* @param string link text
* @param array HTML anchor attributes
* @param string non-default protocol, eg: https
* @param boolean option to escape the title that is output
* @return string
*/
public static function anchor($uri, $title = NULL, $attributes = NULL, $protocol = NULL, $escape_title = FALSE)
{
if ($uri === '')
{
$site_url = url::base(FALSE);
}
elseif (strpos($uri, '#') === 0)
{
// This is an id target link, not a URL
$site_url = $uri;
}
elseif (strpos($uri, '://') === FALSE)
{
$site_url = url::site($uri, $protocol);
}
else
{
if (html::$windowed_urls === TRUE AND empty($attributes['target']))
{
$attributes['target'] = '_blank';
}
$site_url = $uri;
}
return
// Parsed URL
'<a href="'.htmlspecialchars($site_url, ENT_QUOTES, Kohana::CHARSET, FALSE).'"'
// Attributes empty? Use an empty string
.(is_array($attributes) ? html::attributes($attributes) : '').'>'
// Title empty? Use the parsed URL
.($escape_title ? htmlspecialchars((($title === NULL) ? $site_url : $title), ENT_QUOTES, Kohana::CHARSET, FALSE) : (($title === NULL) ? $site_url : $title)).'</a>';
}
/**
* Creates an HTML anchor to a file.
*
* @param string name of file to link to
* @param string link text
* @param array HTML anchor attributes
* @param string non-default protocol, eg: ftp
* @return string
*/
public static function file_anchor($file, $title = NULL, $attributes = NULL, $protocol = NULL)
{
return
// Base URL + URI = full URL
'<a href="'.htmlspecialchars(url::base(FALSE, $protocol).$file, ENT_QUOTES, Kohana::CHARSET, FALSE).'"'
// Attributes empty? Use an empty string
.(is_array($attributes) ? html::attributes($attributes) : '').'>'
// Title empty? Use the filename part of the URI
.(($title === NULL) ? end(explode('/', $file)) : $title) .'</a>';
}
/**
* Generates an obfuscated version of an email address.
*
* @param string email address
* @return string
*/
public static function email($email)
{
$safe = '';
foreach (str_split($email) as $letter)
{
switch (($letter === '@') ? rand(1, 2) : rand(1, 3))
{
// HTML entity code
case 1: $safe .= '&#'.ord($letter).';'; break;
// Hex character code
case 2: $safe .= '&#x'.dechex(ord($letter)).';'; break;
// Raw (no) encoding
case 3: $safe .= $letter;
}
}
return $safe;
}
/**
* Creates an email anchor.
*
* @param string email address to send to
* @param string link text
* @param array HTML anchor attributes
* @return string
*/
public static function mailto($email, $title = NULL, $attributes = NULL)
{
if (empty($email))
return $title;
// Remove the subject or other parameters that do not need to be encoded
if (strpos($email, '?') !== FALSE)
{
// Extract the parameters from the email address
list ($email, $params) = explode('?', $email, 2);
// Make the params into a query string, replacing spaces
$params = '?'.str_replace(' ', '%20', $params);
}
else
{
// No parameters
$params = '';
}
// Obfuscate email address
$safe = html::email($email);
// Title defaults to the encoded email address
empty($title) and $title = $safe;
// Parse attributes
empty($attributes) or $attributes = html::attributes($attributes);
// Encoded start of the href="" is a static encoded version of 'mailto:'
return '<a href="&#109;&#097;&#105;&#108;&#116;&#111;&#058;'.$safe.$params.'"'.$attributes.'>'.$title.'</a>';
}
/**
* Generate a "breadcrumb" list of anchors representing the URI.
*
* @param array segments to use as breadcrumbs, defaults to using Router::$segments
* @return string
*/
public static function breadcrumb($segments = NULL)
{
empty($segments) and $segments = Router::$segments;
$array = array();
while ($segment = array_pop($segments))
{
$array[] = html::anchor
(
// Complete URI for the URL
implode('/', $segments).'/'.$segment,
// Title for the current segment
ucwords(inflector::humanize($segment))
);
}
// Retrun the array of all the segments
return array_reverse($array);
}
/**
* Creates a meta tag.
*
* @param string|array tag name, or an array of tags
* @param string tag "content" value
* @return string
*/
public static function meta($tag, $value = NULL)
{
if (is_array($tag))
{
$tags = array();
foreach ($tag as $t => $v)
{
// Build each tag and add it to the array
$tags[] = html::meta($t, $v);
}
// Return all of the tags as a string
return implode("\n", $tags);
}
// Set the meta attribute value
$attr = in_array(strtolower($tag), Kohana::config('http.meta_equiv')) ? 'http-equiv' : 'name';
return '<meta '.$attr.'="'.$tag.'" content="'.$value.'" />';
}
/**
* Creates a stylesheet link.
*
* @param string|array filename, or array of filenames to match to array of medias
* @param string|array media type of stylesheet, or array to match filenames
* @param boolean include the index_page in the link
* @return string
*/
public static function stylesheet($style, $media = FALSE, $index = FALSE)
{
return html::link($style, 'stylesheet', 'text/css', $media, $index);
}
/**
* Creates a link tag.
*
* @param string|array filename
* @param string|array relationship
* @param string|array mimetype
* @param string|array specifies on what device the document will be displayed
* @param boolean include the index_page in the link
* @return string
*/
public static function link($href, $rel, $type, $media = FALSE, $index = FALSE)
{
$compiled = '';
if (is_array($href))
{
foreach ($href as $_href)
{
$_rel = is_array($rel) ? array_shift($rel) : $rel;
$_type = is_array($type) ? array_shift($type) : $type;
$_media = is_array($media) ? array_shift($media) : $media;
$compiled .= html::link($_href, $_rel, $_type, $_media, $index);
}
}
else
{
if (strpos($href, '://') === FALSE)
{
// Make the URL absolute
$href = url::base($index).$href;
}
$attr = array
(
'rel' => $rel,
'type' => $type,
'href' => $href,
);
if ( ! empty($media))
{
// Add the media type to the attributes
$attr['media'] = $media;
}
$compiled = '<link'.html::attributes($attr).' />';
}
return $compiled."\n";
}
/**
* Creates a script link.
*
* @param string|array filename
* @param boolean include the index_page in the link
* @return string
*/
public static function script($script, $index = FALSE)
{
$compiled = '';
if (is_array($script))
{
foreach ($script as $name)
{
$compiled .= html::script($name, $index);
}
}
else
{
if (strpos($script, '://') === FALSE)
{
// Add the suffix only when it's not already present
$script = url::base((bool) $index).$script;
}
$compiled = '<script type="text/javascript" src="'.$script.'"></script>';
}
return $compiled."\n";
}
/**
* Creates a image link.
*
* @param string image source, or an array of attributes
* @param string|array image alt attribute, or an array of attributes
* @param boolean include the index_page in the link
* @return string
*/
public static function image($src = NULL, $alt = NULL, $index = FALSE)
{
// Create attribute list
$attributes = is_array($src) ? $src : array('src' => $src);
if (is_array($alt))
{
$attributes += $alt;
}
elseif ( ! empty($alt))
{
// Add alt to attributes
$attributes['alt'] = $alt;
}
if (strpos($attributes['src'], '://') === FALSE)
{
// Make the src attribute into an absolute URL
$attributes['src'] = url::base($index).$attributes['src'];
}
return '<img'.html::attributes($attributes).' />';
}
/**
* Compiles an array of HTML attributes into an attribute string.
*
* @param string|array array of attributes
* @return string
*/
public static function attributes($attrs)
{
if (empty($attrs))
return '';
if (is_string($attrs))
return ' '.$attrs;
$compiled = '';
foreach ($attrs as $key => $val)
{
$compiled .= ' '.$key.'="'.htmlspecialchars($val, ENT_QUOTES, Kohana::CHARSET).'"';
}
return $compiled;
}
} // End html

View File

@ -0,0 +1,254 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Inflector helper class.
*
* $Id: inflector.php 4679 2009-11-10 01:45:52Z isaiah $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class inflector_Core {
// Cached inflections
protected static $cache = array();
// Uncountable and irregular words
protected static $uncountable;
protected static $irregular;
/**
* Checks if a word is defined as uncountable.
*
* @param string word to check
* @return boolean
*/
public static function uncountable($str)
{
if (inflector::$uncountable === NULL)
{
// Cache uncountables
inflector::$uncountable = Kohana::config('inflector.uncountable');
// Make uncountables mirroed
inflector::$uncountable = array_combine(inflector::$uncountable, inflector::$uncountable);
}
return isset(inflector::$uncountable[strtolower($str)]);
}
/**
* Makes a plural word singular.
*
* @param string word to singularize
* @param integer number of things
* @return string
*/
public static function singular($str, $count = NULL) {
$parts = explode('_', $str);
$last = inflector::_singular(array_pop($parts), $count);
$pre = implode('_', $parts);
if (strlen($pre))
$pre .= '_';
return $pre.$last;
}
/**
* Makes a plural word singular.
*
* @param string word to singularize
* @param integer number of things
* @return string
*/
public static function _singular($str, $count = NULL)
{
// Remove garbage
$str = strtolower(trim($str));
if (is_string($count))
{
// Convert to integer when using a digit string
$count = (int) $count;
}
// Do nothing with a single count
if ($count === 0 OR $count > 1)
return $str;
// Cache key name
$key = 'singular_'.$str.$count;
if (isset(inflector::$cache[$key]))
return inflector::$cache[$key];
if (inflector::uncountable($str))
return inflector::$cache[$key] = $str;
if (empty(inflector::$irregular))
{
// Cache irregular words
inflector::$irregular = Kohana::config('inflector.irregular');
}
if ($irregular = array_search($str, inflector::$irregular))
{
$str = $irregular;
}
elseif (preg_match('/[sxz]es$/', $str) OR preg_match('/[^aeioudgkprt]hes$/', $str))
{
// Remove "es"
$str = substr($str, 0, -2);
}
elseif (preg_match('/[^aeiou]ies$/', $str))
{
$str = substr($str, 0, -3).'y';
}
elseif (substr($str, -1) === 's' AND substr($str, -2) !== 'ss')
{
$str = substr($str, 0, -1);
}
return inflector::$cache[$key] = $str;
}
/**
* Makes a singular word plural.
*
* @param string word to pluralize
* @return string
*/
public static function plural($str, $count = NULL)
{
if ( ! $str)
return $str;
$parts = explode('_', $str);
$last = inflector::_plural(array_pop($parts), $count);
$pre = implode('_', $parts);
if (strlen($pre))
$pre .= '_';
return $pre.$last;
}
/**
* Makes a singular word plural.
*
* @param string word to pluralize
* @return string
*/
public static function _plural($str, $count = NULL)
{
// Remove garbage
$str = strtolower(trim($str));
if (is_string($count))
{
// Convert to integer when using a digit string
$count = (int) $count;
}
// Do nothing with singular
if ($count === 1)
return $str;
// Cache key name
$key = 'plural_'.$str.$count;
if (isset(inflector::$cache[$key]))
return inflector::$cache[$key];
if (inflector::uncountable($str))
return inflector::$cache[$key] = $str;
if (empty(inflector::$irregular))
{
// Cache irregular words
inflector::$irregular = Kohana::config('inflector.irregular');
}
if (isset(inflector::$irregular[$str]))
{
$str = inflector::$irregular[$str];
}
elseif (preg_match('/[sxz]$/', $str) OR preg_match('/[^aeioudgkprt]h$/', $str))
{
$str .= 'es';
}
elseif (preg_match('/[^aeiou]y$/', $str))
{
// Change "y" to "ies"
$str = substr_replace($str, 'ies', -1);
}
else
{
$str .= 's';
}
// Set the cache and return
return inflector::$cache[$key] = $str;
}
/**
* Makes a word possessive.
*
* @param string word to to make possessive
* @return string
*/
public static function possessive($string)
{
$length = strlen($string);
if (substr($string, $length - 1, $length) == 's')
{
return $string.'\'';
}
return $string.'\'s';
}
/**
* Makes a phrase camel case.
*
* @param string phrase to camelize
* @return string
*/
public static function camelize($str)
{
$str = 'x'.strtolower(trim($str));
$str = ucwords(preg_replace('/[\s_]+/', ' ', $str));
return substr(str_replace(' ', '', $str), 1);
}
/**
* Makes a phrase underscored instead of spaced.
*
* @param string phrase to underscore
* @return string
*/
public static function underscore($str)
{
return trim(preg_replace('/[\s_]+/', '_', $str), '_');
}
/**
* Makes an underscored or dashed phrase human-reable.
*
* @param string phrase to make human-reable
* @return string
*/
public static function humanize($str)
{
return trim(preg_replace('/[_-\s]+/', ' ', $str));
}
} // End inflector

View File

@ -0,0 +1,26 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Number helper class.
*
* $Id: num.php 4679 2009-11-10 01:45:52Z isaiah $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class num_Core {
/**
* Round a number to the nearest nth
*
* @param integer number to round
* @param integer number to round to
* @return integer
*/
public static function round($number, $nearest = 5)
{
return round($number / $nearest) * $nearest;
}
} // End num

View File

@ -0,0 +1,66 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Remote url/file helper.
*
* $Id: remote.php 4679 2009-11-10 01:45:52Z isaiah $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class remote_Core {
public static function status($url)
{
if ( ! valid::url($url, 'http'))
return FALSE;
// Get the hostname and path
$url = parse_url($url);
if (empty($url['path']))
{
// Request the root document
$url['path'] = '/';
}
// Open a remote connection
$remote = fsockopen($url['host'], 80, $errno, $errstr, 5);
if ( ! is_resource($remote))
return FALSE;
// Set CRLF
$CRLF = "\r\n";
// Send request
fwrite($remote, 'HEAD '.$url['path'].(isset($url['query']) ? '?'.$url['query'] : '').' HTTP/1.0'.$CRLF);
fwrite($remote, 'Host: '.$url['host'].$CRLF);
fwrite($remote, 'Connection: close'.$CRLF);
fwrite($remote, 'User-Agent: Kohana Framework (+http://kohanaphp.com/)'.$CRLF);
// Send one more CRLF to terminate the headers
fwrite($remote, $CRLF);
while ( ! feof($remote))
{
// Get the line
$line = trim(fgets($remote, 512));
if ($line !== '' AND preg_match('#^HTTP/1\.[01] (\d{3})#', $line, $matches))
{
// Response code found
$response = (int) $matches[1];
break;
}
}
// Close the connection
fclose($remote);
return isset($response) ? $response : FALSE;
}
} // End remote

View File

@ -0,0 +1,619 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Request helper class.
*
* $Id: request.php 4692 2009-12-04 15:59:44Z cbandy $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class request_Core {
// Possible HTTP methods
protected static $http_methods = array('get', 'head', 'options', 'post', 'put', 'delete');
// Character sets from client's HTTP Accept-Charset request header
protected static $accept_charsets;
// Content codings from client's HTTP Accept-Encoding request header
protected static $accept_encodings;
// Language tags from client's HTTP Accept-Language request header
protected static $accept_languages;
// Content types from client's HTTP Accept request header
protected static $accept_types;
// The current user agent and its parsed attributes
protected static $user_agent;
/**
* Returns the HTTP referrer, or the default if the referrer is not set.
*
* @param mixed default to return
* @param bool Remove base URL
* @return string
*/
public static function referrer($default = FALSE, $remove_base = FALSE)
{
if ( ! empty($_SERVER['HTTP_REFERER']))
{
// Set referrer
$ref = $_SERVER['HTTP_REFERER'];
if ($remove_base === TRUE AND (strpos($ref, url::base(FALSE)) === 0))
{
// Remove the base URL from the referrer
$ref = substr($ref, strlen(url::base(FALSE)));
}
}
return isset($ref) ? $ref : $default;
}
/**
* Returns the current request protocol, based on $_SERVER['https']. In CLI
* mode, NULL will be returned.
*
* @return string
*/
public static function protocol()
{
if (Kohana::$server_api === 'cli')
{
return NULL;
}
elseif ( ! empty($_SERVER['HTTPS']) AND $_SERVER['HTTPS'] === 'on')
{
return 'https';
}
else
{
return 'http';
}
}
/**
* Tests if the current request is an AJAX request by checking the X-Requested-With HTTP
* request header that most popular JS frameworks now set for AJAX calls.
*
* @return boolean
*/
public static function is_ajax()
{
return (isset($_SERVER['HTTP_X_REQUESTED_WITH']) AND strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest');
}
/**
* Returns current request method.
*
* @throws Kohana_Exception in case of an unknown request method
* @return string
*/
public static function method()
{
$method = strtolower($_SERVER['REQUEST_METHOD']);
if ( ! in_array($method, request::$http_methods))
throw new Kohana_Exception('Invalid request method :method:', array(':method:' => $method));
return $method;
}
/**
* Retrieves current user agent information
* keys: browser, version, platform, mobile, robot
*
* @param string key
* @return mixed NULL or the parsed value
*/
public static function user_agent($key = 'agent')
{
// Retrieve raw user agent without parsing
if ($key === 'agent')
{
if (request::$user_agent === NULL)
return request::$user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? trim($_SERVER['HTTP_USER_AGENT']) : '';
if (is_array(request::$user_agent))
return request::$user_agent['agent'];
return request::$user_agent;
}
if ( ! is_array(request::$user_agent))
{
request::$user_agent['agent'] = isset($_SERVER['HTTP_USER_AGENT']) ? trim($_SERVER['HTTP_USER_AGENT']) : '';
// Parse the user agent and extract basic information
foreach (Kohana::config('user_agents') as $type => $data)
{
foreach ($data as $fragment => $name)
{
if (stripos(request::$user_agent['agent'], $fragment) !== FALSE)
{
if ($type === 'browser' AND preg_match('|'.preg_quote($fragment).'[^0-9.]*+([0-9.][0-9.a-z]*)|i', request::$user_agent['agent'], $match))
{
// Set the browser version
request::$user_agent['version'] = $match[1];
}
// Set the agent name
request::$user_agent[$type] = $name;
break;
}
}
}
}
return isset(request::$user_agent[$key]) ? request::$user_agent[$key] : NULL;
}
/**
* Returns boolean of whether client accepts content type.
*
* @param string content type
* @param boolean set to TRUE to disable wildcard checking
* @return boolean
*/
public static function accepts($type = NULL, $explicit_check = FALSE)
{
request::parse_accept_content_header();
if ($type === NULL)
return request::$accept_types;
return (request::accepts_at_quality($type, $explicit_check) > 0);
}
/**
* Returns boolean indicating if the client accepts a charset
*
* @param string
* @return boolean
*/
public static function accepts_charset($charset = NULL)
{
request::parse_accept_charset_header();
if ($charset === NULL)
return request::$accept_charsets;
return (request::accepts_charset_at_quality($charset) > 0);
}
/**
* Returns boolean indicating if the client accepts an encoding
*
* @param string
* @param boolean set to TRUE to disable wildcard checking
* @return boolean
*/
public static function accepts_encoding($encoding = NULL, $explicit_check = FALSE)
{
request::parse_accept_encoding_header();
if ($encoding === NULL)
return request::$accept_encodings;
return (request::accepts_encoding_at_quality($encoding, $explicit_check) > 0);
}
/**
* Returns boolean indicating if the client accepts a language tag
*
* @param string language tag
* @param boolean set to TRUE to disable prefix and wildcard checking
* @return boolean
*/
public static function accepts_language($tag = NULL, $explicit_check = FALSE)
{
request::parse_accept_language_header();
if ($tag === NULL)
return request::$accept_languages;
return (request::accepts_language_at_quality($tag, $explicit_check) > 0);
}
/**
* Compare the q values for given array of content types and return the one with the highest value.
* If items are found to have the same q value, the first one encountered in the given array wins.
* If all items in the given array have a q value of 0, FALSE is returned.
*
* @param array content types
* @param boolean set to TRUE to disable wildcard checking
* @return mixed string mime type with highest q value, FALSE if none of the given types are accepted
*/
public static function preferred_accept($types, $explicit_check = FALSE)
{
$max_q = 0;
$preferred = FALSE;
foreach ($types as $type)
{
$q = request::accepts_at_quality($type, $explicit_check);
if ($q > $max_q)
{
$max_q = $q;
$preferred = $type;
}
}
return $preferred;
}
/**
* Compare the q values for a given array of character sets and return the
* one with the highest value. If items are found to have the same q value,
* the first one encountered takes precedence. If all items in the given
* array have a q value of 0, FALSE is returned.
*
* @param array character sets
* @return mixed
*/
public static function preferred_charset($charsets)
{
$max_q = 0;
$preferred = FALSE;
foreach ($charsets as $charset)
{
$q = request::accepts_charset_at_quality($charset);
if ($q > $max_q)
{
$max_q = $q;
$preferred = $charset;
}
}
return $preferred;
}
/**
* Compare the q values for a given array of encodings and return the one with
* the highest value. If items are found to have the same q value, the first
* one encountered takes precedence. If all items in the given array have
* a q value of 0, FALSE is returned.
*
* @param array encodings
* @param boolean set to TRUE to disable wildcard checking
* @return mixed
*/
public static function preferred_encoding($encodings, $explicit_check = FALSE)
{
$max_q = 0;
$preferred = FALSE;
foreach ($encodings as $encoding)
{
$q = request::accepts_encoding_at_quality($encoding, $explicit_check);
if ($q > $max_q)
{
$max_q = $q;
$preferred = $encoding;
}
}
return $preferred;
}
/**
* Compare the q values for a given array of language tags and return the
* one with the highest value. If items are found to have the same q value,
* the first one encountered takes precedence. If all items in the given
* array have a q value of 0, FALSE is returned.
*
* @param array language tags
* @param boolean set to TRUE to disable prefix and wildcard checking
* @return mixed
*/
public static function preferred_language($tags, $explicit_check = FALSE)
{
$max_q = 0;
$preferred = FALSE;
foreach ($tags as $tag)
{
$q = request::accepts_language_at_quality($tag, $explicit_check);
if ($q > $max_q)
{
$max_q = $q;
$preferred = $tag;
}
}
return $preferred;
}
/**
* Returns quality factor at which the client accepts content type
*
* @param string content type (e.g. "image/jpg", "jpg")
* @param boolean set to TRUE to disable wildcard checking
* @return integer|float
*/
public static function accepts_at_quality($type, $explicit_check = FALSE)
{
request::parse_accept_content_header();
// Normalize type
$type = strtolower($type);
// General content type (e.g. "jpg")
if (strpos($type, '/') === FALSE)
{
// Don't accept anything by default
$q = 0;
// Look up relevant mime types
foreach ((array) Kohana::config('mimes.'.$type) as $type)
{
$q2 = request::accepts_at_quality($type, $explicit_check);
$q = ($q2 > $q) ? $q2 : $q;
}
return $q;
}
// Content type with subtype given (e.g. "image/jpg")
$type = explode('/', $type, 2);
// Exact match
if (isset(request::$accept_types[$type[0]][$type[1]]))
return request::$accept_types[$type[0]][$type[1]];
if ($explicit_check === FALSE)
{
// Wildcard match
if (isset(request::$accept_types[$type[0]]['*']))
return request::$accept_types[$type[0]]['*'];
// Catch-all wildcard match
if (isset(request::$accept_types['*']['*']))
return request::$accept_types['*']['*'];
}
// Content type not accepted
return 0;
}
/**
* Returns quality factor at which the client accepts a charset
*
* @param string charset (e.g., "ISO-8859-1", "utf-8")
* @return integer|float
*/
public static function accepts_charset_at_quality($charset)
{
request::parse_accept_charset_header();
// Normalize charset
$charset = strtolower($charset);
// Exact match
if (isset(request::$accept_charsets[$charset]))
return request::$accept_charsets[$charset];
if (isset(request::$accept_charsets['*']))
return request::$accept_charsets['*'];
if ($charset === 'iso-8859-1')
return 1;
return 0;
}
/**
* Returns quality factor at which the client accepts an encoding
*
* @param string encoding (e.g., "gzip", "deflate")
* @param boolean set to TRUE to disable wildcard checking
* @return integer|float
*/
public static function accepts_encoding_at_quality($encoding, $explicit_check = FALSE)
{
request::parse_accept_encoding_header();
// Normalize encoding
$encoding = strtolower($encoding);
// Exact match
if (isset(request::$accept_encodings[$encoding]))
return request::$accept_encodings[$encoding];
if ($explicit_check === FALSE)
{
if (isset(request::$accept_encodings['*']))
return request::$accept_encodings['*'];
if ($encoding === 'identity')
return 1;
}
return 0;
}
/**
* Returns quality factor at which the client accepts a language
*
* @param string tag (e.g., "en", "en-us", "fr-ca")
* @param boolean set to TRUE to disable prefix and wildcard checking
* @return integer|float
*/
public static function accepts_language_at_quality($tag, $explicit_check = FALSE)
{
request::parse_accept_language_header();
$tag = explode('-', strtolower($tag), 2);
if (isset(request::$accept_languages[$tag[0]]))
{
if (isset($tag[1]))
{
// Exact match
if (isset(request::$accept_languages[$tag[0]][$tag[1]]))
return request::$accept_languages[$tag[0]][$tag[1]];
// A prefix matches
if ($explicit_check === FALSE AND isset(request::$accept_languages[$tag[0]]['*']))
return request::$accept_languages[$tag[0]]['*'];
}
else
{
// No subtags
if (isset(request::$accept_languages[$tag[0]]['*']))
return request::$accept_languages[$tag[0]]['*'];
}
}
if ($explicit_check === FALSE AND isset(request::$accept_languages['*']))
return request::$accept_languages['*'];
return 0;
}
/**
* Parses a HTTP Accept or Accept-* header for q values
*
* @param string header data
* @return array
*/
protected static function parse_accept_header($header)
{
$result = array();
// Remove linebreaks and parse the HTTP Accept header
foreach (explode(',', str_replace(array("\r", "\n"), '', strtolower($header))) as $entry)
{
// Explode each entry in content type and possible quality factor
$entry = explode(';', trim($entry), 2);
$q = (isset($entry[1]) AND preg_match('~\bq\s*+=\s*+([.0-9]+)~', $entry[1], $match)) ? (float) $match[1] : 1;
// Overwrite entries with a smaller q value
if ( ! isset($result[$entry[0]]) OR $q > $result[$entry[0]])
{
$result[$entry[0]] = $q;
}
}
return $result;
}
/**
* Parses a client's HTTP Accept-Charset header
*/
protected static function parse_accept_charset_header()
{
// Run this function just once
if (request::$accept_charsets !== NULL)
return;
// No HTTP Accept-Charset header found
if (empty($_SERVER['HTTP_ACCEPT_CHARSET']))
{
// Accept everything
request::$accept_charsets['*'] = 1;
}
else
{
request::$accept_charsets = request::parse_accept_header($_SERVER['HTTP_ACCEPT_CHARSET']);
}
}
/**
* Parses a client's HTTP Accept header
*/
protected static function parse_accept_content_header()
{
// Run this function just once
if (request::$accept_types !== NULL)
return;
// No HTTP Accept header found
if (empty($_SERVER['HTTP_ACCEPT']))
{
// Accept everything
request::$accept_types['*']['*'] = 1;
}
else
{
request::$accept_types = array();
foreach (request::parse_accept_header($_SERVER['HTTP_ACCEPT']) as $type => $q)
{
// Explode each content type (e.g. "text/html")
$type = explode('/', $type, 2);
// Skip invalid content types
if ( ! isset($type[1]))
continue;
request::$accept_types[$type[0]][$type[1]] = $q;
}
}
}
/**
* Parses a client's HTTP Accept-Encoding header
*/
protected static function parse_accept_encoding_header()
{
// Run this function just once
if (request::$accept_encodings !== NULL)
return;
// No HTTP Accept-Encoding header found
if ( ! isset($_SERVER['HTTP_ACCEPT_ENCODING']))
{
// Accept everything
request::$accept_encodings['*'] = 1;
}
elseif ($_SERVER['HTTP_ACCEPT_ENCODING'] === '')
{
// Accept only identity
request::$accept_encodings['identity'] = 1;
}
else
{
request::$accept_encodings = request::parse_accept_header($_SERVER['HTTP_ACCEPT_ENCODING']);
}
}
/**
* Parses a client's HTTP Accept-Language header
*/
protected static function parse_accept_language_header()
{
// Run this function just once
if (request::$accept_languages !== NULL)
return;
// No HTTP Accept-Language header found
if (empty($_SERVER['HTTP_ACCEPT_LANGUAGE']))
{
// Accept everything
request::$accept_languages['*'] = 1;
}
else
{
request::$accept_languages = array();
foreach (request::parse_accept_header($_SERVER['HTTP_ACCEPT_LANGUAGE']) as $tag => $q)
{
// Explode each language (e.g. "en-us")
$tag = explode('-', $tag, 2);
request::$accept_languages[$tag[0]][isset($tag[1]) ? $tag[1] : '*'] = $q;
}
}
}
} // End request

View File

@ -0,0 +1,37 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Security helper class.
*
* $Id: security.php 4698 2009-12-08 18:39:33Z isaiah $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class security_Core {
/**
* Sanitize a string with the xss_clean method.
*
* @param string string to sanitize
* @param string xss_clean method to use ('htmlpurifier' or defaults to built-in method)
* @return string
*/
public static function xss_clean($str, $tool = NULL)
{
return Input::instance()->xss_clean($str, $tool);
}
/**
* Remove image tags from a string.
*
* @param string string to sanitize
* @return string
*/
public static function strip_image_tags($str)
{
return preg_replace('#<img\s.*?(?:src\s*=\s*["\']?([^"\'<>\s]*)["\']?[^>]*)?>#is', '$1', $str);
}
} // End security

View File

@ -0,0 +1,598 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Text helper class.
*
* $Id: text.php 4689 2009-12-02 01:39:24Z isaiah $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class text_Core {
/**
* Limits a phrase to a given number of words.
*
* @param string phrase to limit words of
* @param integer number of words to limit to
* @param string end character or entity
* @return string
*/
public static function limit_words($str, $limit = 100, $end_char = NULL)
{
$limit = (int) $limit;
$end_char = ($end_char === NULL) ? '&#8230;' : $end_char;
if (trim($str) === '')
return $str;
if ($limit <= 0)
return $end_char;
preg_match('/^\s*+(?:\S++\s*+){1,'.$limit.'}/u', $str, $matches);
// Only attach the end character if the matched string is shorter
// than the starting string.
return rtrim($matches[0]).(strlen($matches[0]) === strlen($str) ? '' : $end_char);
}
/**
* Limits a phrase to a given number of characters.
*
* @param string phrase to limit characters of
* @param integer number of characters to limit to
* @param string end character or entity
* @param boolean enable or disable the preservation of words while limiting
* @return string
*/
public static function limit_chars($str, $limit = 100, $end_char = NULL, $preserve_words = FALSE)
{
$end_char = ($end_char === NULL) ? '&#8230;' : $end_char;
$limit = (int) $limit;
if (trim($str) === '' OR mb_strlen($str) <= $limit)
return $str;
if ($limit <= 0)
return $end_char;
if ($preserve_words == FALSE)
{
return rtrim(mb_substr($str, 0, $limit)).$end_char;
}
preg_match('/^.{'.($limit - 1).'}\S*/us', $str, $matches);
return rtrim($matches[0]).(strlen($matches[0]) == strlen($str) ? '' : $end_char);
}
/**
* Alternates between two or more strings.
*
* @param string strings to alternate between
* @return string
*/
public static function alternate()
{
static $i;
if (func_num_args() === 0)
{
$i = 0;
return '';
}
$args = func_get_args();
return $args[($i++ % count($args))];
}
/**
* Generates a random string of a given type and length.
*
* @param string a type of pool, or a string of characters to use as the pool
* @param integer length of string to return
* @return string
*
* @tutorial alnum alpha-numeric characters
* @tutorial alpha alphabetical characters
* @tutorial hexdec hexadecimal characters, 0-9 plus a-f
* @tutorial numeric digit characters, 0-9
* @tutorial nozero digit characters, 1-9
* @tutorial distinct clearly distinct alpha-numeric characters
*/
public static function random($type = 'alnum', $length = 8)
{
$utf8 = FALSE;
switch ($type)
{
case 'alnum':
$pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
break;
case 'alpha':
$pool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
break;
case 'hexdec':
$pool = '0123456789abcdef';
break;
case 'numeric':
$pool = '0123456789';
break;
case 'nozero':
$pool = '123456789';
break;
case 'distinct':
$pool = '2345679ACDEFHJKLMNPRSTUVWXYZ';
break;
default:
$pool = (string) $type;
$utf8 = ! text::is_ascii($pool);
break;
}
// Split the pool into an array of characters
$pool = ($utf8 === TRUE) ? utf8::str_split($pool, 1) : str_split($pool, 1);
// Largest pool key
$max = count($pool) - 1;
$str = '';
for ($i = 0; $i < $length; $i++)
{
// Select a random character from the pool and add it to the string
$str .= $pool[mt_rand(0, $max)];
}
// Make sure alnum strings contain at least one letter and one digit
if ($type === 'alnum' AND $length > 1)
{
if (ctype_alpha($str))
{
// Add a random digit
$str[mt_rand(0, $length - 1)] = chr(mt_rand(48, 57));
}
elseif (ctype_digit($str))
{
// Add a random letter
$str[mt_rand(0, $length - 1)] = chr(mt_rand(65, 90));
}
}
return $str;
}
/**
* Reduces multiple slashes in a string to single slashes.
*
* @param string string to reduce slashes of
* @return string
*/
public static function reduce_slashes($str)
{
return preg_replace('#(?<!:)//+#', '/', $str);
}
/**
* Replaces the given words with a string.
*
* @param string phrase to replace words in
* @param array words to replace
* @param string replacement string
* @param boolean replace words across word boundries (space, period, etc)
* @return string
*/
public static function censor($str, $badwords, $replacement = '#', $replace_partial_words = TRUE)
{
foreach ((array) $badwords as $key => $badword)
{
$badwords[$key] = str_replace('\*', '\S*?', preg_quote((string) $badword));
}
$regex = '('.implode('|', $badwords).')';
if ($replace_partial_words === FALSE)
{
// Just using \b isn't sufficient when we need to replace a badword that already contains word boundaries itself
$regex = '(?<=\b|\s|^)'.$regex.'(?=\b|\s|$)';
}
$regex = '!'.$regex.'!ui';
if (mb_strlen($replacement) == 1)
{
$regex .= 'e';
return preg_replace($regex, 'str_repeat($replacement, mb_strlen(\'$1\'))', $str);
}
return preg_replace($regex, $replacement, $str);
}
/**
* Finds the text that is similar between a set of words.
*
* @param array words to find similar text of
* @return string
*/
public static function similar(array $words)
{
// First word is the word to match against
$word = current($words);
for ($i = 0, $max = strlen($word); $i < $max; ++$i)
{
foreach ($words as $w)
{
// Once a difference is found, break out of the loops
if ( ! isset($w[$i]) OR $w[$i] !== $word[$i])
break 2;
}
}
// Return the similar text
return substr($word, 0, $i);
}
/**
* An alternative to the php levenshtein() function that work out the
* distance between 2 words using the DamerauLevenshtein algorithm.
* Credit: http://forums.devnetwork.net/viewtopic.php?f=50&t=89094
*
* @see http://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance
* @param string first word
* @param string second word
* @return int distance between words
*/
public static function distance($string1, $string2)
{
$string1_length = strlen($string1);
$string2_length = strlen($string2);
// Here we start building the table of values
$matrix = array();
// String1 length + 1 = rows.
for ($i = 0; $i <= $string1_length; ++$i)
{
$matrix[$i][0] = $i;
}
// String2 length + 1 columns.
for ($j = 0; $j <= $string2_length; ++$j)
{
$matrix[0][$j] = $j;
}
for ($i = 1; $i <= $string1_length; ++$i)
{
for ($j = 1; $j <= $string2_length; ++$j)
{
$cost = substr($string1, $i - 1, 1) == substr($string2, $j - 1, 1) ? 0 : 1;
$matrix[$i][$j] = min(
$matrix[$i - 1][$j] + 1, // deletion
$matrix[$i][$j - 1] + 1, // insertion
$matrix[$i - 1][$j - 1] + $cost // substitution
);
if ($i > 1 && $j > 1 && (substr($string1, $i - 1, 1) == substr($string2, $j - 2, 1))
&& (substr($string1, $i - 2, 1) == substr($string2, $j - 1, 1)))
{
$matrix[$i][$j] = min(
$matrix[$i][$j],
$matrix[$i - 2][$j - 2] + $cost // transposition
);
}
}
}
return $matrix[$string1_length][$string2_length];
}
/**
* Converts text anchors into links.
*
* @param string text to auto link
* @return string
*/
public static function auto_link_urls($text)
{
$regex = '~\\b'
.'((?:ht|f)tps?://)?' // protocol
.'(?:[-a-zA-Z0-9]{1,63}\.)+' // host name
.'(?:[0-9]{1,3}|aero|asia|biz|cat|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|su|sv|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)' // tlds
.'(?:/[!$-/0-9:;=@_\':;!a-zA-Z\x7f-\xff]*?)?' // path
.'(?:\?[!$-/0-9:;=@_\':;!a-zA-Z\x7f-\xff]+?)?' // query
.'(?:#[!$-/0-9:;=@_\':;!a-zA-Z\x7f-\xff]+?)?' // fragment
.'(?=[?.!,;:"]?(?:\s|$))~'; // punctuation and url end
$result = "";
$position = 0;
while (preg_match($regex, $text, $match, PREG_OFFSET_CAPTURE, $position))
{
list($url, $url_pos) = $match[0];
// Add the text before the url
$result .= substr($text, $position, $url_pos - $position);
// Default to http://
$full_url = empty($match[1][0]) ? 'http://'.$url : $url;
// Add the hyperlink.
$result .= html::anchor($full_url, $url);
// New position to start parsing
$position = $url_pos + strlen($url);
}
return $result.substr($text, $position);
}
/**
* Converts text email addresses into links.
*
* @param string text to auto link
* @return string
*/
public static function auto_link_emails($text)
{
// Finds all email addresses that are not part of an existing html mailto anchor
// Note: The "58;" negative lookbehind prevents matching of existing encoded html mailto anchors
// The html entity for a colon (:) is &#58; or &#058; or &#0058; etc.
if (preg_match_all('~\b(?<!href="mailto:|">|58;)(?!\.)[-+_a-z0-9.]++(?<!\.)@(?![-.])[-a-z0-9.]+(?<!\.)\.[a-z]{2,6}\b~i', $text, $matches))
{
foreach ($matches[0] as $match)
{
// Replace each email with an encoded mailto
$text = str_replace($match, html::mailto($match), $text);
}
}
return $text;
}
/**
* Automatically applies <p> and <br /> markup to text. Basically nl2br() on steroids.
*
* @param string subject
* @param boolean convert single linebreaks to <br />
* @return string
*/
public static function auto_p($str, $br = TRUE)
{
// Trim whitespace
if (($str = trim($str)) === '')
return '';
// Standardize newlines
$str = str_replace(array("\r\n", "\r"), "\n", $str);
// Trim whitespace on each line
$str = preg_replace('~^[ \t]+~m', '', $str);
$str = preg_replace('~[ \t]+$~m', '', $str);
// The following regexes only need to be executed if the string contains html
if ($html_found = (strpos($str, '<') !== FALSE))
{
// Elements that should not be surrounded by p tags
$no_p = '(?:p|div|h[1-6r]|ul|ol|li|blockquote|d[dlt]|pre|t[dhr]|t(?:able|body|foot|head)|c(?:aption|olgroup)|form|s(?:elect|tyle)|a(?:ddress|rea)|ma(?:p|th))';
// Put at least two linebreaks before and after $no_p elements
$str = preg_replace('~^<'.$no_p.'[^>]*+>~im', "\n$0", $str);
$str = preg_replace('~</'.$no_p.'\s*+>$~im', "$0\n", $str);
}
// Do the <p> magic!
$str = '<p>'.trim($str).'</p>';
$str = preg_replace('~\n{2,}~', "</p>\n\n<p>", $str);
// The following regexes only need to be executed if the string contains html
if ($html_found !== FALSE)
{
// Remove p tags around $no_p elements
$str = preg_replace('~<p>(?=</?'.$no_p.'[^>]*+>)~i', '', $str);
$str = preg_replace('~(</?'.$no_p.'[^>]*+>)</p>~i', '$1', $str);
}
// Convert single linebreaks to <br />
if ($br === TRUE)
{
$str = preg_replace('~(?<!\n)\n(?!\n)~', "<br />\n", $str);
}
return $str;
}
/**
* Returns human readable sizes.
* @see Based on original functions written by:
* @see Aidan Lister: http://aidanlister.com/repos/v/function.size_readable.php
* @see Quentin Zervaas: http://www.phpriot.com/d/code/strings/filesize-format/
*
* @param integer size in bytes
* @param string a definitive unit
* @param string the return string format
* @param boolean whether to use SI prefixes or IEC
* @return string
*/
public static function bytes($bytes, $force_unit = NULL, $format = NULL, $si = TRUE)
{
// Format string
$format = ($format === NULL) ? '%01.2f %s' : (string) $format;
// IEC prefixes (binary)
if ($si == FALSE OR strpos($force_unit, 'i') !== FALSE)
{
$units = array(__('B'), __('KiB'), __('MiB'), __('GiB'), __('TiB'), __('PiB'));
$mod = 1024;
}
// SI prefixes (decimal)
else
{
$units = array(__('B'), __('kB'), __('MB'), __('GB'), __('TB'), __('PB'));
$mod = 1000;
}
// Determine unit to use
if (($power = array_search((string) $force_unit, $units)) === FALSE)
{
$power = ($bytes > 0) ? floor(log($bytes, $mod)) : 0;
}
return sprintf($format, $bytes / pow($mod, $power), $units[$power]);
}
/**
* Prevents widow words by inserting a non-breaking space between the last two words.
* @see http://www.shauninman.com/archive/2006/08/22/widont_wordpress_plugin
*
* @param string string to remove widows from
* @return string
*/
public static function widont($str)
{
$str = rtrim($str);
$space = strrpos($str, ' ');
if ($space !== FALSE)
{
$str = substr($str, 0, $space).'&nbsp;'.substr($str, $space + 1);
}
return $str;
}
/**
* Tests whether a string contains only 7bit ASCII bytes. This is used to
* determine when to use native functions or UTF-8 functions.
*
* @see http://sourceforge.net/projects/phputf8/
* @copyright (c) 2007-2009 Kohana Team
* @copyright (c) 2005 Harry Fuecks
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
*
* @param string string to check
* @return bool
*/
public static function is_ascii($str)
{
return is_string($str) AND ! preg_match('/[^\x00-\x7F]/S', $str);
}
/**
* Strips out device control codes in the ASCII range.
*
* @see http://sourceforge.net/projects/phputf8/
* @copyright (c) 2007-2009 Kohana Team
* @copyright (c) 2005 Harry Fuecks
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
*
* @param string string to clean
* @return string
*/
public static function strip_ascii_ctrl($str)
{
return preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S', '', $str);
}
/**
* Strips out all non-7bit ASCII bytes.
*
* @see http://sourceforge.net/projects/phputf8/
* @copyright (c) 2007-2009 Kohana Team
* @copyright (c) 2005 Harry Fuecks
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
*
* @param string string to clean
* @return string
*/
public static function strip_non_ascii($str)
{
return preg_replace('/[^\x00-\x7F]+/S', '', $str);
}
/**
* Replaces special/accented UTF-8 characters by ASCII-7 'equivalents'.
*
* @author Andreas Gohr <andi@splitbrain.org>
* @see http://sourceforge.net/projects/phputf8/
* @copyright (c) 2007-2009 Kohana Team
* @copyright (c) 2005 Harry Fuecks
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
*
* @param string string to transliterate
* @param integer -1 lowercase only, +1 uppercase only, 0 both cases
* @return string
*/
public static function transliterate_to_ascii($str, $case = 0)
{
static $UTF8_LOWER_ACCENTS = NULL;
static $UTF8_UPPER_ACCENTS = NULL;
if ($case <= 0)
{
if ($UTF8_LOWER_ACCENTS === NULL)
{
$UTF8_LOWER_ACCENTS = array(
'à' => 'a', 'ô' => 'o', 'ď' => 'd', 'ḟ' => 'f', 'ë' => 'e', 'š' => 's', 'ơ' => 'o',
'ß' => 'ss', 'ă' => 'a', 'ř' => 'r', 'ț' => 't', 'ň' => 'n', 'ā' => 'a', 'ķ' => 'k',
'ŝ' => 's', 'ỳ' => 'y', 'ņ' => 'n', 'ĺ' => 'l', 'ħ' => 'h', 'ṗ' => 'p', 'ó' => 'o',
'ú' => 'u', 'ě' => 'e', 'é' => 'e', 'ç' => 'c', 'ẁ' => 'w', 'ċ' => 'c', 'õ' => 'o',
'ṡ' => 's', 'ø' => 'o', 'ģ' => 'g', 'ŧ' => 't', 'ș' => 's', 'ė' => 'e', 'ĉ' => 'c',
'ś' => 's', 'î' => 'i', 'ű' => 'u', 'ć' => 'c', 'ę' => 'e', 'ŵ' => 'w', 'ṫ' => 't',
'ū' => 'u', 'č' => 'c', 'ö' => 'o', 'è' => 'e', 'ŷ' => 'y', 'ą' => 'a', 'ł' => 'l',
'ų' => 'u', 'ů' => 'u', 'ş' => 's', 'ğ' => 'g', 'ļ' => 'l', 'ƒ' => 'f', 'ž' => 'z',
'ẃ' => 'w', 'ḃ' => 'b', 'å' => 'a', 'ì' => 'i', 'ï' => 'i', 'ḋ' => 'd', 'ť' => 't',
'ŗ' => 'r', 'ä' => 'a', 'í' => 'i', 'ŕ' => 'r', 'ê' => 'e', 'ü' => 'u', 'ò' => 'o',
'ē' => 'e', 'ñ' => 'n', 'ń' => 'n', 'ĥ' => 'h', 'ĝ' => 'g', 'đ' => 'd', 'ĵ' => 'j',
'ÿ' => 'y', 'ũ' => 'u', 'ŭ' => 'u', 'ư' => 'u', 'ţ' => 't', 'ý' => 'y', 'ő' => 'o',
'â' => 'a', 'ľ' => 'l', 'ẅ' => 'w', 'ż' => 'z', 'ī' => 'i', 'ã' => 'a', 'ġ' => 'g',
'ṁ' => 'm', 'ō' => 'o', 'ĩ' => 'i', 'ù' => 'u', 'į' => 'i', 'ź' => 'z', 'á' => 'a',
'û' => 'u', 'þ' => 'th', 'ð' => 'dh', 'æ' => 'ae', 'µ' => 'u', 'ĕ' => 'e', 'ı' => 'i',
);
}
$str = str_replace(
array_keys($UTF8_LOWER_ACCENTS),
array_values($UTF8_LOWER_ACCENTS),
$str
);
}
if ($case >= 0)
{
if ($UTF8_UPPER_ACCENTS === NULL)
{
$UTF8_UPPER_ACCENTS = array(
'À' => 'A', 'Ô' => 'O', 'Ď' => 'D', 'Ḟ' => 'F', 'Ë' => 'E', 'Š' => 'S', 'Ơ' => 'O',
'Ă' => 'A', 'Ř' => 'R', 'Ț' => 'T', 'Ň' => 'N', 'Ā' => 'A', 'Ķ' => 'K', 'Ĕ' => 'E',
'Ŝ' => 'S', 'Ỳ' => 'Y', 'Ņ' => 'N', 'Ĺ' => 'L', 'Ħ' => 'H', 'Ṗ' => 'P', 'Ó' => 'O',
'Ú' => 'U', 'Ě' => 'E', 'É' => 'E', 'Ç' => 'C', 'Ẁ' => 'W', 'Ċ' => 'C', 'Õ' => 'O',
'Ṡ' => 'S', 'Ø' => 'O', 'Ģ' => 'G', 'Ŧ' => 'T', 'Ș' => 'S', 'Ė' => 'E', 'Ĉ' => 'C',
'Ś' => 'S', 'Î' => 'I', 'Ű' => 'U', 'Ć' => 'C', 'Ę' => 'E', 'Ŵ' => 'W', 'Ṫ' => 'T',
'Ū' => 'U', 'Č' => 'C', 'Ö' => 'O', 'È' => 'E', 'Ŷ' => 'Y', 'Ą' => 'A', 'Ł' => 'L',
'Ų' => 'U', 'Ů' => 'U', 'Ş' => 'S', 'Ğ' => 'G', 'Ļ' => 'L', 'Ƒ' => 'F', 'Ž' => 'Z',
'Ẃ' => 'W', 'Ḃ' => 'B', 'Å' => 'A', 'Ì' => 'I', 'Ï' => 'I', 'Ḋ' => 'D', 'Ť' => 'T',
'Ŗ' => 'R', 'Ä' => 'A', 'Í' => 'I', 'Ŕ' => 'R', 'Ê' => 'E', 'Ü' => 'U', 'Ò' => 'O',
'Ē' => 'E', 'Ñ' => 'N', 'Ń' => 'N', 'Ĥ' => 'H', 'Ĝ' => 'G', 'Đ' => 'D', 'Ĵ' => 'J',
'Ÿ' => 'Y', 'Ũ' => 'U', 'Ŭ' => 'U', 'Ư' => 'U', 'Ţ' => 'T', 'Ý' => 'Y', 'Ő' => 'O',
'Â' => 'A', 'Ľ' => 'L', 'Ẅ' => 'W', 'Ż' => 'Z', 'Ī' => 'I', 'Ã' => 'A', 'Ġ' => 'G',
'Ṁ' => 'M', 'Ō' => 'O', 'Ĩ' => 'I', 'Ù' => 'U', 'Į' => 'I', 'Ź' => 'Z', 'Á' => 'A',
'Û' => 'U', 'Þ' => 'Th', 'Ð' => 'Dh', 'Æ' => 'Ae', 'İ' => 'I',
);
}
$str = str_replace(
array_keys($UTF8_UPPER_ACCENTS),
array_values($UTF8_UPPER_ACCENTS),
$str
);
}
return $str;
}
} // End text

View File

@ -0,0 +1,159 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Upload helper class for working with the global $_FILES
* array and Validation library.
*
* $Id: upload.php 4679 2009-11-10 01:45:52Z isaiah $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class upload_Core {
/**
* Save an uploaded file to a new location.
*
* @param mixed name of $_FILE input or array of upload data
* @param string new filename
* @param string new directory
* @param integer chmod mask
* @return string full path to new file
*/
public static function save($file, $filename = NULL, $directory = NULL, $chmod = 0644)
{
// Load file data from FILES if not passed as array
$file = is_array($file) ? $file : $_FILES[$file];
if ($filename === NULL)
{
// Use the default filename, with a timestamp pre-pended
$filename = time().$file['name'];
}
if (Kohana::config('upload.remove_spaces') === TRUE)
{
// Remove spaces from the filename
$filename = preg_replace('/\s+/', '_', $filename);
}
if ($directory === NULL)
{
// Use the pre-configured upload directory
$directory = Kohana::config('upload.directory', TRUE);
}
// Make sure the directory ends with a slash
$directory = rtrim($directory, '/').'/';
if ( ! is_dir($directory) AND Kohana::config('upload.create_directories') === TRUE)
{
// Create the upload directory
mkdir($directory, 0777, TRUE);
}
if ( ! is_writable($directory))
throw new Kohana_Exception('The upload destination folder, :dir:, does not appear to be writable.', array(':dir:' => $directory));
if (is_uploaded_file($file['tmp_name']) AND move_uploaded_file($file['tmp_name'], $filename = $directory.$filename))
{
if ($chmod !== FALSE)
{
// Set permissions on filename
chmod($filename, $chmod);
}
// Return new file path
return $filename;
}
return FALSE;
}
/* Validation Rules */
/**
* Tests if input data is valid file type, even if no upload is present.
*
* @param array $_FILES item
* @return bool
*/
public static function valid($file)
{
return (is_array($file)
AND isset($file['error'])
AND isset($file['name'])
AND isset($file['type'])
AND isset($file['tmp_name'])
AND isset($file['size']));
}
/**
* Tests if input data has valid upload data.
*
* @param array $_FILES item
* @return bool
*/
public static function required(array $file)
{
return (isset($file['tmp_name'])
AND isset($file['error'])
AND is_uploaded_file($file['tmp_name'])
AND (int) $file['error'] === UPLOAD_ERR_OK);
}
/**
* Validation rule to test if an uploaded file is allowed by extension.
*
* @param array $_FILES item
* @param array allowed file extensions
* @return bool
*/
public static function type(array $file, array $allowed_types)
{
if ((int) $file['error'] !== UPLOAD_ERR_OK)
return TRUE;
// Get the default extension of the file
$extension = strtolower(substr(strrchr($file['name'], '.'), 1));
// Make sure there is an extension and that the extension is allowed
return ( ! empty($extension) AND in_array($extension, $allowed_types));
}
/**
* Validation rule to test if an uploaded file is allowed by file size.
* File sizes are defined as: SB, where S is the size (1, 15, 300, etc) and
* B is the byte modifier: (B)ytes, (K)ilobytes, (M)egabytes, (G)igabytes.
* Eg: to limit the size to 1MB or less, you would use "1M".
*
* @param array $_FILES item
* @param array maximum file size
* @return bool
*/
public static function size(array $file, array $size)
{
if ((int) $file['error'] !== UPLOAD_ERR_OK)
return TRUE;
// Only one size is allowed
$size = strtoupper($size[0]);
if ( ! preg_match('/[0-9]++[BKMG]/', $size))
return FALSE;
// Make the size into a power of 1024
switch (substr($size, -1))
{
case 'G': $size = intval($size) * pow(1024, 3); break;
case 'M': $size = intval($size) * pow(1024, 2); break;
case 'K': $size = intval($size) * pow(1024, 1); break;
default: $size = intval($size); break;
}
// Test that the file is under or equal to the max size
return ($file['size'] <= $size);
}
} // End upload

View File

@ -0,0 +1,264 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* URL helper class.
*
* $Id: url.php 4685 2009-11-30 21:24:06Z isaiah $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class url_Core {
/**
* Fetches the current URI.
*
* @param boolean include the query string
* @param boolean include the suffix
* @return string
*/
public static function current($qs = FALSE, $suffix = FALSE)
{
$uri = ($qs === TRUE) ? Router::$complete_uri : Router::$current_uri;
return ($suffix === TRUE) ? $uri.Kohana::config('core.url_suffix') : $uri;
}
/**
* Base URL, with or without the index page.
*
* If protocol (and core.site_protocol) and core.site_domain are both empty,
* then
*
* @param boolean include the index page
* @param boolean non-default protocol
* @return string
*/
public static function base($index = FALSE, $protocol = FALSE)
{
if ($protocol == FALSE)
{
// Use the default configured protocol
$protocol = Kohana::config('core.site_protocol');
}
// Load the site domain
$site_domain = (string) Kohana::config('core.site_domain', TRUE);
if ($protocol == FALSE)
{
if ($site_domain === '' OR $site_domain[0] === '/')
{
// Use the configured site domain
$base_url = $site_domain;
}
else
{
// Guess the protocol to provide full http://domain/path URL
$base_url = ((empty($_SERVER['HTTPS']) OR $_SERVER['HTTPS'] === 'off') ? 'http' : 'https').'://'.$site_domain;
}
}
else
{
if ($site_domain === '' OR $site_domain[0] === '/')
{
// Guess the server name if the domain starts with slash
$base_url = $protocol.'://'.$_SERVER['HTTP_HOST'].$site_domain;
}
else
{
// Use the configured site domain
$base_url = $protocol.'://'.$site_domain;
}
}
if ($index === TRUE AND $index = Kohana::config('core.index_page'))
{
// Append the index page
$base_url = $base_url.$index;
}
// Force a slash on the end of the URL
return rtrim($base_url, '/').'/';
}
/**
* Fetches an absolute site URL based on a URI segment.
*
* @param string site URI to convert
* @param string non-default protocol
* @return string
*/
public static function site($uri = '', $protocol = FALSE)
{
if ($path = trim(parse_url($uri, PHP_URL_PATH), '/'))
{
// Add path suffix
$path .= Kohana::config('core.url_suffix');
}
if ($query = parse_url($uri, PHP_URL_QUERY))
{
// ?query=string
$query = '?'.$query;
}
if ($fragment = parse_url($uri, PHP_URL_FRAGMENT))
{
// #fragment
$fragment = '#'.$fragment;
}
// Concat the URL
return url::base(TRUE, $protocol).$path.$query.$fragment;
}
/**
* Return the URL to a file. Absolute filenames and relative filenames
* are allowed.
*
* @param string filename
* @param boolean include the index page
* @return string
*/
public static function file($file, $index = FALSE)
{
if (strpos($file, '://') === FALSE)
{
// Add the base URL to the filename
$file = url::base($index).$file;
}
return $file;
}
/**
* Merges an array of arguments with the current URI and query string to
* overload, instead of replace, the current query string.
*
* @param array associative array of arguments
* @return string
*/
public static function merge(array $arguments)
{
if ($_GET === $arguments)
{
$query = Router::$query_string;
}
elseif ($query = http_build_query(array_merge($_GET, $arguments)))
{
$query = '?'.$query;
}
// Return the current URI with the arguments merged into the query string
return Router::$current_uri.$query;
}
/**
* Convert a phrase to a URL-safe title.
*
* @param string phrase to convert
* @param string word separator (- or _)
* @param boolean transliterate to ASCII
* @return string
*/
public static function title($title, $separator = '-', $ascii_only = FALSE)
{
$separator = ($separator === '-') ? '-' : '_';
if ($ascii_only === TRUE)
{
// Replace accented characters by their unaccented equivalents
$title = text::transliterate_to_ascii($title);
// Remove all characters that are not the separator, a-z, 0-9, or whitespace
$title = preg_replace('/[^'.$separator.'a-z0-9\s]+/', '', strtolower($title));
}
else
{
// Remove all characters that are not the separator, letters, numbers, or whitespace
$title = preg_replace('/[^'.$separator.'\pL\pN\s]+/u', '', mb_strtolower($title));
}
// Replace all separator characters and whitespace by a single separator
$title = preg_replace('/['.$separator.'\s]+/', $separator, $title);
// Trim separators from the beginning and end
return trim($title, $separator);
}
/**
* Sends a page redirect header and runs the system.redirect Event.
*
* @param mixed string site URI or URL to redirect to, or array of strings if method is 300
* @param string HTTP method of redirect
* @return void
*/
public static function redirect($uri = '', $method = '302')
{
if (Event::has_run('system.send_headers'))
{
return FALSE;
}
$codes = array
(
'refresh' => 'Refresh',
'300' => 'Multiple Choices',
'301' => 'Moved Permanently',
'302' => 'Found',
'303' => 'See Other',
'304' => 'Not Modified',
'305' => 'Use Proxy',
'307' => 'Temporary Redirect'
);
// Validate the method and default to 302
$method = isset($codes[$method]) ? (string) $method : '302';
if ($method === '300')
{
$uri = (array) $uri;
$output = '<ul>';
foreach ($uri as $link)
{
$output .= '<li>'.html::anchor($link).'</li>';
}
$output .= '</ul>';
// The first URI will be used for the Location header
$uri = $uri[0];
}
else
{
$output = '<p>'.html::anchor($uri).'</p>';
}
// Run the redirect event
Event::run('system.redirect', $uri);
if (strpos($uri, '://') === FALSE)
{
// HTTP headers expect absolute URLs
$uri = url::site($uri, request::protocol());
}
if ($method === 'refresh')
{
header('Refresh: 0; url='.$uri);
}
else
{
header('HTTP/1.1 '.$method.' '.$codes[$method]);
header('Location: '.$uri);
}
// We are about to exit, so run the send_headers event
Event::run('system.send_headers');
exit('<h1>'.$method.' - '.$codes[$method].'</h1>'.$output);
}
} // End url

View File

@ -0,0 +1,746 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* A port of phputf8 to a unified file/class.
*
* This file is licensed differently from the rest of Kohana. As a port of
* phputf8, which is LGPL software, this file is released under the LGPL.
*
* PCRE needs to be compiled with UTF-8 support (--enable-utf8).
* Support for Unicode properties is highly recommended (--enable-unicode-properties).
* @see http://php.net/manual/reference.pcre.pattern.modifiers.php
*
* string functions.
* @see http://php.net/mbstring
*
* $Id$
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @copyright (c) 2005 Harry Fuecks
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
*/
class utf8 {
/**
* Replaces text within a portion of a UTF-8 string.
* @see http://php.net/substr_replace
*
* @author Harry Fuecks <hfuecks@gmail.com>
*
* @param string input string
* @param string replacement string
* @param integer offset
* @return string
*/
public static function substr_replace($str, $replacement, $offset, $length = NULL)
{
if (text::is_ascii($str))
return ($length === NULL) ? substr_replace($str, $replacement, $offset) : substr_replace($str, $replacement, $offset, $length);
$length = ($length === NULL) ? mb_strlen($str) : (int) $length;
preg_match_all('/./us', $str, $str_array);
preg_match_all('/./us', $replacement, $replacement_array);
array_splice($str_array[0], $offset, $length, $replacement_array[0]);
return implode('', $str_array[0]);
}
/**
* Makes a UTF-8 string's first character uppercase.
* @see http://php.net/ucfirst
*
* @author Harry Fuecks <hfuecks@gmail.com>
*
* @param string mixed case string
* @return string
*/
public static function ucfirst($str)
{
if (text::is_ascii($str))
return ucfirst($str);
preg_match('/^(.?)(.*)$/us', $str, $matches);
return mb_strtoupper($matches[1]).$matches[2];
}
/**
* Case-insensitive UTF-8 string comparison.
* @see http://php.net/strcasecmp
*
* @author Harry Fuecks <hfuecks@gmail.com>
*
* @param string string to compare
* @param string string to compare
* @return integer less than 0 if str1 is less than str2
* @return integer greater than 0 if str1 is greater than str2
* @return integer 0 if they are equal
*/
public static function strcasecmp($str1, $str2)
{
if (text::is_ascii($str1) AND text::is_ascii($str2))
return strcasecmp($str1, $str2);
$str1 = mb_strtolower($str1);
$str2 = mb_strtolower($str2);
return strcmp($str1, $str2);
}
/**
* Returns a string or an array with all occurrences of search in subject (ignoring case).
* replaced with the given replace value.
* @see http://php.net/str_ireplace
*
* @note It's not fast and gets slower if $search and/or $replace are arrays.
* @author Harry Fuecks <hfuecks@gmail.com
*
* @param string|array text to replace
* @param string|array replacement text
* @param string|array subject text
* @param integer number of matched and replaced needles will be returned via this parameter which is passed by reference
* @return string if the input was a string
* @return array if the input was an array
*/
public static function str_ireplace($search, $replace, $str, & $count = NULL)
{
if (text::is_ascii($search) AND text::is_ascii($replace) AND text::is_ascii($str))
return str_ireplace($search, $replace, $str, $count);
if (is_array($str))
{
foreach ($str as $key => $val)
{
$str[$key] = utf8::str_ireplace($search, $replace, $val, $count);
}
return $str;
}
if (is_array($search))
{
$keys = array_keys($search);
foreach ($keys as $k)
{
if (is_array($replace))
{
if (array_key_exists($k, $replace))
{
$str = utf8::str_ireplace($search[$k], $replace[$k], $str, $count);
}
else
{
$str = utf8::str_ireplace($search[$k], '', $str, $count);
}
}
else
{
$str = utf8::str_ireplace($search[$k], $replace, $str, $count);
}
}
return $str;
}
$search = mb_strtolower($search);
$str_lower = mb_strtolower($str);
$total_matched_strlen = 0;
$i = 0;
while (preg_match('/(.*?)'.preg_quote($search, '/').'/s', $str_lower, $matches))
{
$matched_strlen = strlen($matches[0]);
$str_lower = substr($str_lower, $matched_strlen);
$offset = $total_matched_strlen + strlen($matches[1]) + ($i * (strlen($replace) - 1));
$str = substr_replace($str, $replace, $offset, strlen($search));
$total_matched_strlen += $matched_strlen;
$i++;
}
$count += $i;
return $str;
}
/**
* Case-insenstive UTF-8 version of strstr. Returns all of input string
* from the first occurrence of needle to the end.
* @see http://php.net/stristr
*
* @author Harry Fuecks <hfuecks@gmail.com>
*
* @param string input string
* @param string needle
* @return string matched substring if found
* @return boolean FALSE if the substring was not found
*/
public static function stristr($str, $search)
{
if (text::is_ascii($str) AND text::is_ascii($search))
return stristr($str, $search);
if ($search == '')
return $str;
$str_lower = mb_strtolower($str);
$search_lower = mb_strtolower($search);
preg_match('/^(.*?)'.preg_quote($search, '/').'/s', $str_lower, $matches);
if (isset($matches[1]))
return substr($str, strlen($matches[1]));
return FALSE;
}
/**
* Finds the length of the initial segment matching mask.
* @see http://php.net/strspn
*
* @author Harry Fuecks <hfuecks@gmail.com>
*
* @param string input string
* @param string mask for search
* @param integer start position of the string to examine
* @param integer length of the string to examine
* @return integer length of the initial segment that contains characters in the mask
*/
public static function strspn($str, $mask, $offset = NULL, $length = NULL)
{
if ($str == '' OR $mask == '')
return 0;
if (text::is_ascii($str) AND text::is_ascii($mask))
return ($offset === NULL) ? strspn($str, $mask) : (($length === NULL) ? strspn($str, $mask, $offset) : strspn($str, $mask, $offset, $length));
if ($offset !== NULL OR $length !== NULL)
{
$str = mb_substr($str, $offset, $length);
}
// Escape these characters: - [ ] . : \ ^ /
// The . and : are escaped to prevent possible warnings about POSIX regex elements
$mask = preg_replace('#[-[\].:\\\\^/]#', '\\\\$0', $mask);
preg_match('/^[^'.$mask.']+/u', $str, $matches);
return isset($matches[0]) ? mb_strlen($matches[0]) : 0;
}
/**
* Finds the length of the initial segment not matching mask.
* @see http://php.net/strcspn
*
* @author Harry Fuecks <hfuecks@gmail.com>
*
* @param string input string
* @param string mask for search
* @param integer start position of the string to examine
* @param integer length of the string to examine
* @return integer length of the initial segment that contains characters not in the mask
*/
public static function strcspn($str, $mask, $offset = NULL, $length = NULL)
{
if ($str == '' OR $mask == '')
return 0;
if (text::is_ascii($str) AND text::is_ascii($mask))
return ($offset === NULL) ? strcspn($str, $mask) : (($length === NULL) ? strcspn($str, $mask, $offset) : strcspn($str, $mask, $offset, $length));
if ($str !== NULL OR $length !== NULL)
{
$str = mb_substr($str, $offset, $length);
}
// Escape these characters: - [ ] . : \ ^ /
// The . and : are escaped to prevent possible warnings about POSIX regex elements
$mask = preg_replace('#[-[\].:\\\\^/]#', '\\\\$0', $mask);
preg_match('/^[^'.$mask.']+/u', $str, $matches);
return isset($matches[0]) ? mb_strlen($matches[0]) : 0;
}
/**
* Pads a UTF-8 string to a certain length with another string.
* @see http://php.net/str_pad
*
* @author Harry Fuecks <hfuecks@gmail.com>
*
* @param string input string
* @param integer desired string length after padding
* @param string string to use as padding
* @param string padding type: STR_PAD_RIGHT, STR_PAD_LEFT, or STR_PAD_BOTH
* @return string
*/
public static function str_pad($str, $final_str_length, $pad_str = ' ', $pad_type = STR_PAD_RIGHT)
{
if (text::is_ascii($str) AND text::is_ascii($pad_str))
{
return str_pad($str, $final_str_length, $pad_str, $pad_type);
}
$str_length = mb_strlen($str);
if ($final_str_length <= 0 OR $final_str_length <= $str_length)
{
return $str;
}
$pad_str_length = mb_strlen($pad_str);
$pad_length = $final_str_length - $str_length;
if ($pad_type == STR_PAD_RIGHT)
{
$repeat = ceil($pad_length / $pad_str_length);
return mb_substr($str.str_repeat($pad_str, $repeat), 0, $final_str_length);
}
if ($pad_type == STR_PAD_LEFT)
{
$repeat = ceil($pad_length / $pad_str_length);
return mb_substr(str_repeat($pad_str, $repeat), 0, floor($pad_length)).$str;
}
if ($pad_type == STR_PAD_BOTH)
{
$pad_length /= 2;
$pad_length_left = floor($pad_length);
$pad_length_right = ceil($pad_length);
$repeat_left = ceil($pad_length_left / $pad_str_length);
$repeat_right = ceil($pad_length_right / $pad_str_length);
$pad_left = mb_substr(str_repeat($pad_str, $repeat_left), 0, $pad_length_left);
$pad_right = mb_substr(str_repeat($pad_str, $repeat_right), 0, $pad_length_left);
return $pad_left.$str.$pad_right;
}
trigger_error('utf8::str_pad: Unknown padding type (' . $pad_type . ')', E_USER_ERROR);
}
/**
* Converts a UTF-8 string to an array.
* @see http://php.net/str_split
*
* @author Harry Fuecks <hfuecks@gmail.com>
*
* @param string input string
* @param integer maximum length of each chunk
* @return array
*/
public static function str_split($str, $split_length = 1)
{
$split_length = (int) $split_length;
if (text::is_ascii($str))
{
return str_split($str, $split_length);
}
if ($split_length < 1)
{
return FALSE;
}
if (mb_strlen($str) <= $split_length)
{
return array($str);
}
preg_match_all('/.{'.$split_length.'}|[^\x00]{1,'.$split_length.'}$/us', $str, $matches);
return $matches[0];
}
/**
* Reverses a UTF-8 string.
* @see http://php.net/strrev
*
* @author Harry Fuecks <hfuecks@gmail.com>
*
* @param string string to be reversed
* @return string
*/
public static function strrev($str)
{
if (text::is_ascii($str))
return strrev($str);
preg_match_all('/./us', $str, $matches);
return implode('', array_reverse($matches[0]));
}
/**
* Strips whitespace (or other UTF-8 characters) from the beginning and
* end of a string.
* @see http://php.net/trim
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param string input string
* @param string string of characters to remove
* @return string
*/
public static function trim($str, $charlist = NULL)
{
if ($charlist === NULL)
return trim($str);
return utf8::ltrim(utf8::rtrim($str, $charlist), $charlist);
}
/**
* Strips whitespace (or other UTF-8 characters) from the beginning of a string.
* @see http://php.net/ltrim
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param string input string
* @param string string of characters to remove
* @return string
*/
public static function ltrim($str, $charlist = NULL)
{
if ($charlist === NULL)
return ltrim($str);
if (text::is_ascii($charlist))
return ltrim($str, $charlist);
$charlist = preg_replace('#[-\[\]:\\\\^/]#', '\\\\$0', $charlist);
return preg_replace('/^['.$charlist.']+/u', '', $str);
}
/**
* Strips whitespace (or other UTF-8 characters) from the end of a string.
* @see http://php.net/rtrim
*
* @author Andreas Gohr <andi@splitbrain.org>
*
* @param string input string
* @param string string of characters to remove
* @return string
*/
public static function rtrim($str, $charlist = NULL)
{
if ($charlist === NULL)
return rtrim($str);
if (text::is_ascii($charlist))
return rtrim($str, $charlist);
$charlist = preg_replace('#[-\[\]:\\\\^/]#', '\\\\$0', $charlist);
return preg_replace('/['.$charlist.']++$/uD', '', $str);
}
/**
* Returns the unicode ordinal for a character.
* @see http://php.net/ord
*
* @author Harry Fuecks <hfuecks@gmail.com>
*
* @param string UTF-8 encoded character
* @return integer
*/
public static function ord($chr)
{
$ord0 = ord($chr);
if ($ord0 >= 0 AND $ord0 <= 127)
{
return $ord0;
}
if ( ! isset($chr[1]))
{
trigger_error('Short sequence - at least 2 bytes expected, only 1 seen', E_USER_WARNING);
return FALSE;
}
$ord1 = ord($chr[1]);
if ($ord0 >= 192 AND $ord0 <= 223)
{
return ($ord0 - 192) * 64 + ($ord1 - 128);
}
if ( ! isset($chr[2]))
{
trigger_error('Short sequence - at least 3 bytes expected, only 2 seen', E_USER_WARNING);
return FALSE;
}
$ord2 = ord($chr[2]);
if ($ord0 >= 224 AND $ord0 <= 239)
{
return ($ord0 - 224) * 4096 + ($ord1 - 128) * 64 + ($ord2 - 128);
}
if ( ! isset($chr[3]))
{
trigger_error('Short sequence - at least 4 bytes expected, only 3 seen', E_USER_WARNING);
return FALSE;
}
$ord3 = ord($chr[3]);
if ($ord0 >= 240 AND $ord0 <= 247)
{
return ($ord0 - 240) * 262144 + ($ord1 - 128) * 4096 + ($ord2-128) * 64 + ($ord3 - 128);
}
if ( ! isset($chr[4]))
{
trigger_error('Short sequence - at least 5 bytes expected, only 4 seen', E_USER_WARNING);
return FALSE;
}
$ord4 = ord($chr[4]);
if ($ord0 >= 248 AND $ord0 <= 251)
{
return ($ord0 - 248) * 16777216 + ($ord1-128) * 262144 + ($ord2 - 128) * 4096 + ($ord3 - 128) * 64 + ($ord4 - 128);
}
if ( ! isset($chr[5]))
{
trigger_error('Short sequence - at least 6 bytes expected, only 5 seen', E_USER_WARNING);
return FALSE;
}
if ($ord0 >= 252 AND $ord0 <= 253)
{
return ($ord0 - 252) * 1073741824 + ($ord1 - 128) * 16777216 + ($ord2 - 128) * 262144 + ($ord3 - 128) * 4096 + ($ord4 - 128) * 64 + (ord($chr[5]) - 128);
}
if ($ord0 >= 254 AND $ord0 <= 255)
{
trigger_error('Invalid UTF-8 with surrogate ordinal '.$ord0, E_USER_WARNING);
return FALSE;
}
}
/**
* Takes an UTF-8 string and returns an array of ints representing the Unicode characters.
* Astral planes are supported i.e. the ints in the output can be > 0xFFFF.
* Occurrances of the BOM are ignored. Surrogates are not allowed.
*
* The Original Code is Mozilla Communicator client code.
* The Initial Developer of the Original Code is Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998 the Initial Developer.
* Ported to PHP by Henri Sivonen <hsivonen@iki.fi>, see http://hsivonen.iki.fi/php-utf8/.
* Slight modifications to fit with phputf8 library by Harry Fuecks <hfuecks@gmail.com>.
*
* @param string UTF-8 encoded string
* @return array unicode code points
* @return boolean FALSE if the string is invalid
*/
public static function to_unicode($str)
{
$mState = 0; // cached expected number of octets after the current octet until the beginning of the next UTF8 character sequence
$mUcs4 = 0; // cached Unicode character
$mBytes = 1; // cached expected number of octets in the current sequence
$out = array();
$len = strlen($str);
for ($i = 0; $i < $len; $i++)
{
$in = ord($str[$i]);
if ($mState == 0)
{
// When mState is zero we expect either a US-ASCII character or a
// multi-octet sequence.
if (0 == (0x80 & $in))
{
// US-ASCII, pass straight through.
$out[] = $in;
$mBytes = 1;
}
elseif (0xC0 == (0xE0 & $in))
{
// First octet of 2 octet sequence
$mUcs4 = $in;
$mUcs4 = ($mUcs4 & 0x1F) << 6;
$mState = 1;
$mBytes = 2;
}
elseif (0xE0 == (0xF0 & $in))
{
// First octet of 3 octet sequence
$mUcs4 = $in;
$mUcs4 = ($mUcs4 & 0x0F) << 12;
$mState = 2;
$mBytes = 3;
}
elseif (0xF0 == (0xF8 & $in))
{
// First octet of 4 octet sequence
$mUcs4 = $in;
$mUcs4 = ($mUcs4 & 0x07) << 18;
$mState = 3;
$mBytes = 4;
}
elseif (0xF8 == (0xFC & $in))
{
// First octet of 5 octet sequence.
//
// This is illegal because the encoded codepoint must be either
// (a) not the shortest form or
// (b) outside the Unicode range of 0-0x10FFFF.
// Rather than trying to resynchronize, we will carry on until the end
// of the sequence and let the later error handling code catch it.
$mUcs4 = $in;
$mUcs4 = ($mUcs4 & 0x03) << 24;
$mState = 4;
$mBytes = 5;
}
elseif (0xFC == (0xFE & $in))
{
// First octet of 6 octet sequence, see comments for 5 octet sequence.
$mUcs4 = $in;
$mUcs4 = ($mUcs4 & 1) << 30;
$mState = 5;
$mBytes = 6;
}
else
{
// Current octet is neither in the US-ASCII range nor a legal first octet of a multi-octet sequence.
trigger_error('utf8::to_unicode: Illegal sequence identifier in UTF-8 at byte '.$i, E_USER_WARNING);
return FALSE;
}
}
else
{
// When mState is non-zero, we expect a continuation of the multi-octet sequence
if (0x80 == (0xC0 & $in))
{
// Legal continuation
$shift = ($mState - 1) * 6;
$tmp = $in;
$tmp = ($tmp & 0x0000003F) << $shift;
$mUcs4 |= $tmp;
// End of the multi-octet sequence. mUcs4 now contains the final Unicode codepoint to be output
if (0 == --$mState)
{
// Check for illegal sequences and codepoints
// From Unicode 3.1, non-shortest form is illegal
if (((2 == $mBytes) AND ($mUcs4 < 0x0080)) OR
((3 == $mBytes) AND ($mUcs4 < 0x0800)) OR
((4 == $mBytes) AND ($mUcs4 < 0x10000)) OR
(4 < $mBytes) OR
// From Unicode 3.2, surrogate characters are illegal
(($mUcs4 & 0xFFFFF800) == 0xD800) OR
// Codepoints outside the Unicode range are illegal
($mUcs4 > 0x10FFFF))
{
trigger_error('utf8::to_unicode: Illegal sequence or codepoint in UTF-8 at byte '.$i, E_USER_WARNING);
return FALSE;
}
if (0xFEFF != $mUcs4)
{
// BOM is legal but we don't want to output it
$out[] = $mUcs4;
}
// Initialize UTF-8 cache
$mState = 0;
$mUcs4 = 0;
$mBytes = 1;
}
}
else
{
// ((0xC0 & (*in) != 0x80) AND (mState != 0))
// Incomplete multi-octet sequence
trigger_error('utf8::to_unicode: Incomplete multi-octet sequence in UTF-8 at byte '.$i, E_USER_WARNING);
return FALSE;
}
}
}
return $out;
}
/**
* Takes an array of ints representing the Unicode characters and returns a UTF-8 string.
* Astral planes are supported i.e. the ints in the input can be > 0xFFFF.
* Occurrances of the BOM are ignored. Surrogates are not allowed.
*
* The Original Code is Mozilla Communicator client code.
* The Initial Developer of the Original Code is Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998 the Initial Developer.
* Ported to PHP by Henri Sivonen <hsivonen@iki.fi>, see http://hsivonen.iki.fi/php-utf8/.
* Slight modifications to fit with phputf8 library by Harry Fuecks <hfuecks@gmail.com>.
*
* @param array unicode code points representing a string
* @return string utf8 string of characters
* @return boolean FALSE if a code point cannot be found
*/
public static function from_unicode($arr)
{
ob_start();
$keys = array_keys($arr);
foreach ($keys as $k)
{
// ASCII range (including control chars)
if (($arr[$k] >= 0) AND ($arr[$k] <= 0x007f))
{
echo chr($arr[$k]);
}
// 2 byte sequence
elseif ($arr[$k] <= 0x07ff)
{
echo chr(0xc0 | ($arr[$k] >> 6));
echo chr(0x80 | ($arr[$k] & 0x003f));
}
// Byte order mark (skip)
elseif ($arr[$k] == 0xFEFF)
{
// nop -- zap the BOM
}
// Test for illegal surrogates
elseif ($arr[$k] >= 0xD800 AND $arr[$k] <= 0xDFFF)
{
// Found a surrogate
trigger_error('utf8::from_unicode: Illegal surrogate at index: '.$k.', value: '.$arr[$k], E_USER_WARNING);
return FALSE;
}
// 3 byte sequence
elseif ($arr[$k] <= 0xffff)
{
echo chr(0xe0 | ($arr[$k] >> 12));
echo chr(0x80 | (($arr[$k] >> 6) & 0x003f));
echo chr(0x80 | ($arr[$k] & 0x003f));
}
// 4 byte sequence
elseif ($arr[$k] <= 0x10ffff)
{
echo chr(0xf0 | ($arr[$k] >> 18));
echo chr(0x80 | (($arr[$k] >> 12) & 0x3f));
echo chr(0x80 | (($arr[$k] >> 6) & 0x3f));
echo chr(0x80 | ($arr[$k] & 0x3f));
}
// Out of range
else
{
trigger_error('utf8::from_unicode: Codepoint out of Unicode range at index: '.$k.', value: '.$arr[$k], E_USER_WARNING);
return FALSE;
}
}
$result = ob_get_contents();
ob_end_clean();
return $result;
}
} // End utf8

View File

@ -0,0 +1,366 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Validation helper class.
*
* $Id: valid.php 4679 2009-11-10 01:45:52Z isaiah $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class valid_Core {
/**
* Validate email, commonly used characters only
*
* @param string email address
* @return boolean
*/
public static function email($email)
{
return (bool) preg_match('/^[-_a-z0-9\'+*$^&%=~!?{}]++(?:\.[-_a-z0-9\'+*$^&%=~!?{}]+)*+@(?:(?![-.])[-a-z0-9.]+(?<![-.])\.[a-z]{2,6}|\d{1,3}(?:\.\d{1,3}){3})(?::\d++)?$/iD', (string) $email);
}
/**
* Validate the domain of an email address by checking if the domain has a
* valid MX record.
*
* @param string email address
* @return boolean
*/
public static function email_domain($email)
{
// If we can't prove the domain is invalid, consider it valid
// Note: checkdnsrr() is not implemented on Windows platforms
if ( ! function_exists('checkdnsrr'))
return TRUE;
// Check if the email domain has a valid MX record
return (bool) checkdnsrr(preg_replace('/^[^@]+@/', '', $email), 'MX');
}
/**
* Validate email, RFC compliant version
* Note: This function is LESS strict than valid_email. Choose carefully.
*
* @see Originally by Cal Henderson, modified to fit Kohana syntax standards:
* @see http://www.iamcal.com/publish/articles/php/parsing_email/
* @see http://www.w3.org/Protocols/rfc822/
*
* @param string email address
* @return boolean
*/
public static function email_rfc($email)
{
$qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]';
$dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]';
$atom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+';
$pair = '\\x5c[\\x00-\\x7f]';
$domain_literal = "\\x5b($dtext|$pair)*\\x5d";
$quoted_string = "\\x22($qtext|$pair)*\\x22";
$sub_domain = "($atom|$domain_literal)";
$word = "($atom|$quoted_string)";
$domain = "$sub_domain(\\x2e$sub_domain)*";
$local_part = "$word(\\x2e$word)*";
$addr_spec = "$local_part\\x40$domain";
return (bool) preg_match('/^'.$addr_spec.'$/D', (string) $email);
}
/**
* Validate URL
*
* @param string URL
* @return boolean
*/
public static function url($url)
{
return (bool) filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED);
}
/**
* Validate IP
*
* @param string IP address
* @param boolean allow IPv6 addresses
* @param boolean allow private IP networks
* @return boolean
*/
public static function ip($ip, $ipv6 = FALSE, $allow_private = TRUE)
{
// By default do not allow private and reserved range IPs
$flags = FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;
if ($allow_private === TRUE)
$flags = FILTER_FLAG_NO_RES_RANGE;
if ($ipv6 === TRUE)
return (bool) filter_var($ip, FILTER_VALIDATE_IP, $flags);
return (bool) filter_var($ip, FILTER_VALIDATE_IP, $flags | FILTER_FLAG_IPV4);
}
/**
* Validates a credit card number using the Luhn (mod10) formula.
* @see http://en.wikipedia.org/wiki/Luhn_algorithm
*
* @param integer credit card number
* @param string|array card type, or an array of card types
* @return boolean
*/
public static function credit_card($number, $type = NULL)
{
// Remove all non-digit characters from the number
if (($number = preg_replace('/\D+/', '', $number)) === '')
return FALSE;
if ($type == NULL)
{
// Use the default type
$type = 'default';
}
elseif (is_array($type))
{
foreach ($type as $t)
{
// Test each type for validity
if (valid::credit_card($number, $t))
return TRUE;
}
return FALSE;
}
$cards = Kohana::config('credit_cards');
// Check card type
$type = strtolower($type);
if ( ! isset($cards[$type]))
return FALSE;
// Check card number length
$length = strlen($number);
// Validate the card length by the card type
if ( ! in_array($length, preg_split('/\D+/', $cards[$type]['length'])))
return FALSE;
// Check card number prefix
if ( ! preg_match('/^'.$cards[$type]['prefix'].'/', $number))
return FALSE;
// No Luhn check required
if ($cards[$type]['luhn'] == FALSE)
return TRUE;
// Checksum of the card number
$checksum = 0;
for ($i = $length - 1; $i >= 0; $i -= 2)
{
// Add up every 2nd digit, starting from the right
$checksum += substr($number, $i, 1);
}
for ($i = $length - 2; $i >= 0; $i -= 2)
{
// Add up every 2nd digit doubled, starting from the right
$double = substr($number, $i, 1) * 2;
// Subtract 9 from the double where value is greater than 10
$checksum += ($double >= 10) ? $double - 9 : $double;
}
// If the checksum is a multiple of 10, the number is valid
return ($checksum % 10 === 0);
}
/**
* Checks if a phone number is valid.
*
* @param string phone number to check
* @return boolean
*/
public static function phone($number, $lengths = NULL)
{
if ( ! is_array($lengths))
{
$lengths = array(7,10,11);
}
// Remove all non-digit characters from the number
$number = preg_replace('/\D+/', '', $number);
// Check if the number is within range
return in_array(strlen($number), $lengths);
}
/**
* Tests if a string is a valid date string.
*
* @param string date to check
* @return boolean
*/
public static function date($str)
{
return (strtotime($str) !== FALSE);
}
/**
* Checks whether a string consists of alphabetical characters only.
*
* @param string input string
* @param boolean trigger UTF-8 compatibility
* @return boolean
*/
public static function alpha($str, $utf8 = FALSE)
{
return ($utf8 === TRUE)
? (bool) preg_match('/^\pL++$/uD', (string) $str)
: ctype_alpha((string) $str);
}
/**
* Checks whether a string consists of alphabetical characters and numbers only.
*
* @param string input string
* @param boolean trigger UTF-8 compatibility
* @return boolean
*/
public static function alpha_numeric($str, $utf8 = FALSE)
{
return ($utf8 === TRUE)
? (bool) preg_match('/^[\pL\pN]++$/uD', (string) $str)
: ctype_alnum((string) $str);
}
/**
* Checks whether a string consists of alphabetical characters, numbers, underscores and dashes only.
*
* @param string input string
* @param boolean trigger UTF-8 compatibility
* @return boolean
*/
public static function alpha_dash($str, $utf8 = FALSE)
{
return ($utf8 === TRUE)
? (bool) preg_match('/^[-\pL\pN_]++$/uD', (string) $str)
: (bool) preg_match('/^[-a-z0-9_]++$/iD', (string) $str);
}
/**
* Checks whether a string consists of digits only (no dots or dashes).
*
* @param string input string
* @param boolean trigger UTF-8 compatibility
* @return boolean
*/
public static function digit($str, $utf8 = FALSE)
{
return ($utf8 === TRUE)
? (bool) preg_match('/^\pN++$/uD', (string) $str)
: ctype_digit((string) $str);
}
/**
* Checks whether a string is a valid number (negative and decimal numbers allowed).
*
* @see Uses locale conversion to allow decimal point to be locale specific.
* @see http://www.php.net/manual/en/function.localeconv.php
*
* @param string input string
* @return boolean
*/
public static function numeric($str)
{
// Use localeconv to set the decimal_point value: Usually a comma or period.
$locale = localeconv();
return (bool) preg_match('/^-?[0-9'.$locale['decimal_point'].']++$/D', (string) $str);
}
/**
* Tests if an integer is within a range.
*
* @param integer number to check
* @param array valid range of input
* @return boolean
*/
public static function range($number, array $range)
{
// Invalid by default
$status = FALSE;
if (is_int($number) OR ctype_digit($number))
{
if (count($range) > 1)
{
if ($number >= $range[0] AND $number <= $range[1])
{
// Number is within the required range
$status = TRUE;
}
}
elseif ($number >= $range[0])
{
// Number is greater than the minimum
$status = TRUE;
}
}
return $status;
}
/**
* Checks if a string is a proper decimal format. The format array can be
* used to specify a decimal length, or a number and decimal length, eg:
* array(2) would force the number to have 2 decimal places, array(4,2)
* would force the number to have 4 digits and 2 decimal places.
*
* @param string input string
* @param array decimal format: y or x,y
* @return boolean
*/
public static function decimal($str, $format = NULL)
{
// Create the pattern
$pattern = '/^[0-9]%s\.[0-9]%s$/';
if ( ! empty($format))
{
if (count($format) > 1)
{
// Use the format for number and decimal length
$pattern = sprintf($pattern, '{'.$format[0].'}', '{'.$format[1].'}');
}
elseif (count($format) > 0)
{
// Use the format as decimal length
$pattern = sprintf($pattern, '+', '{'.$format[0].'}');
}
}
else
{
// No format
$pattern = sprintf($pattern, '+', '+');
}
return (bool) preg_match($pattern, (string) $str);
}
/**
* Checks if a string is a proper hexadecimal HTML color value. The validation
* is quite flexible as it does not require an initial "#" and also allows for
* the short notation using only three instead of six hexadecimal characters.
* You may want to normalize these values with format::color().
*
* @param string input string
* @return boolean
*/
public static function color($str)
{
return (bool) preg_match('/^#?+[0-9a-f]{3}(?:[0-9a-f]{3})?$/iD', $str);
}
} // End valid

View File

@ -0,0 +1,250 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Provides a driver-based interface for finding, creating, and deleting cached
* resources. Caches are identified by a unique string. Tagging of caches is
* also supported, and caches can be found and deleted by id or tag.
*
* $Id: Cache.php 4605 2009-09-14 17:22:21Z kiall $
*
* @package Cache
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class Cache_Core {
protected static $instances = array();
// Configuration
protected $config;
// Driver object
protected $driver;
/**
* Returns a singleton instance of Cache.
*
* @param string configuration
* @return Cache_Core
*/
public static function & instance($config = FALSE)
{
if ( ! isset(Cache::$instances[$config]))
{
// Create a new instance
Cache::$instances[$config] = new Cache($config);
}
return Cache::$instances[$config];
}
/**
* Loads the configured driver and validates it.
*
* @param array|string custom configuration or config group name
* @return void
*/
public function __construct($config = FALSE)
{
if (is_string($config))
{
$name = $config;
// Test the config group name
if (($config = Kohana::config('cache.'.$config)) === NULL)
throw new Cache_Exception('The :group: group is not defined in your configuration.', array(':group:' => $name));
}
if (is_array($config))
{
// Append the default configuration options
$config += Kohana::config('cache.default');
}
else
{
// Load the default group
$config = Kohana::config('cache.default');
}
// Cache the config in the object
$this->config = $config;
// Set driver name
$driver = 'Cache_'.ucfirst($this->config['driver']).'_Driver';
// Load the driver
if ( ! Kohana::auto_load($driver))
throw new Cache_Exception('The :driver: driver for the :class: library could not be found',
array(':driver:' => $this->config['driver'], ':class:' => get_class($this)));
// Initialize the driver
$this->driver = new $driver($this->config['params']);
// Validate the driver
if ( ! ($this->driver instanceof Cache_Driver))
throw new Cache_Exception('The :driver: driver for the :library: library must implement the :interface: interface',
array(':driver:' => $this->config['driver'], ':library:' => get_class($this), ':interface:' => 'Cache_Driver'));
Kohana_Log::add('debug', 'Cache Library initialized');
}
/**
* Set cache items
*/
public function set($key, $value = NULL, $tags = NULL, $lifetime = NULL)
{
if ($lifetime === NULL)
{
$lifetime = $this->config['lifetime'];
}
if ( ! is_array($key))
{
$key = array($key => $value);
}
if ($this->config['prefix'] !== NULL)
{
$key = $this->add_prefix($key);
if ($tags !== NULL)
{
$tags = $this->add_prefix($tags, FALSE);
}
}
return $this->driver->set($key, $tags, $lifetime);
}
/**
* Get a cache items by key
*/
public function get($keys)
{
$single = FALSE;
if ( ! is_array($keys))
{
$keys = array($keys);
$single = TRUE;
}
if ($this->config['prefix'] !== NULL)
{
$keys = $this->add_prefix($keys, FALSE);
if ( ! $single)
{
return $this->strip_prefix($this->driver->get($keys, $single));
}
}
return $this->driver->get($keys, $single);
}
/**
* Get cache items by tags
*/
public function get_tag($tags)
{
if ( ! is_array($tags))
{
$tags = array($tags);
}
if ($this->config['prefix'] !== NULL)
{
$tags = $this->add_prefix($tags, FALSE);
return $this->strip_prefix($this->driver->get_tag($tags));
}
else
{
return $this->driver->get_tag($tags);
}
}
/**
* Delete cache item by key
*/
public function delete($keys)
{
if ( ! is_array($keys))
{
$keys = array($keys);
}
if ($this->config['prefix'] !== NULL)
{
$keys = $this->add_prefix($keys, FALSE);
}
return $this->driver->delete($keys);
}
/**
* Delete cache items by tag
*/
public function delete_tag($tags)
{
if ( ! is_array($tags))
{
$tags = array($tags);
}
if ($this->config['prefix'] !== NULL)
{
$tags = $this->add_prefix($tags, FALSE);
}
return $this->driver->delete_tag($tags);
}
/**
* Empty the cache
*/
public function delete_all()
{
return $this->driver->delete_all();
}
/**
* Add a prefix to keys or tags
*/
protected function add_prefix($array, $to_key = TRUE)
{
$out = array();
foreach($array as $key => $value)
{
if ($to_key)
{
$out[$this->config['prefix'].$key] = $value;
}
else
{
$out[$key] = $this->config['prefix'].$value;
}
}
return $out;
}
/**
* Strip a prefix to keys or tags
*/
protected function strip_prefix($array)
{
$out = array();
$start = strlen($this->config['prefix']);
foreach($array as $key => $value)
{
$out[substr($key, $start)] = $value;
}
return $out;
}
} // End Cache Library

View File

@ -0,0 +1,12 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* $Id: Kohana_User_Exception.php 4543 2009-09-04 16:58:56Z nodren $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class Cache_Exception_Core extends Kohana_Exception {}
// End Kohana User Exception

View File

@ -0,0 +1,51 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
* Kohana Controller class. The controller class must be extended to work
* properly, so this class is defined as abstract.
*
* $Id: Controller.php 4679 2009-11-10 01:45:52Z isaiah $
*
* @package Core
* @author Kohana Team
* @copyright (c) 2007-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
abstract class Controller_Core {
// Allow all controllers to run in production by default
const ALLOW_PRODUCTION = TRUE;
/**
* Loads URI, and Input into this controller.
*
* @return void
*/
public function __construct()
{
if (Kohana::$instance == NULL)
{
// Set the instance to the first controller loaded
Kohana::$instance = $this;
}
// URI should always be available
$this->uri = URI::instance();
// Input should always be available
$this->input = Input::instance();
}
/**
* Handles methods that do not exist.
*
* @param string method name
* @param array arguments
* @return void
*/
public function __call($method, $args)
{
// Default to showing a 404 page
Event::run('system.404');
}
} // End Controller Class

View File

@ -0,0 +1,645 @@
<?php defined('SYSPATH') or die('No direct script access.');
/**
* Database wrapper.
*
* $Id: Database.php 4709 2009-12-10 05:09:35Z isaiah $
*
* @package Kohana
* @author Kohana Team
* @copyright (c) 2008-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
abstract class Database_Core {
const SELECT = 1;
const INSERT = 2;
const UPDATE = 3;
const DELETE = 4;
const CROSS_REQUEST = 5;
const PER_REQUEST = 6;
protected static $instances = array();
// Global benchmarks
public static $benchmarks = array();
// Last execute query
protected $last_query;
// Configuration array
protected $config;
// Required configuration keys
protected $config_required = array();
// Raw server connection
protected $connection;
// Cache (Cache object for cross-request, array for per-request)
protected $cache;
// Quote character to use for identifiers (tables/columns/aliases)
protected $quote = '"';
/**
* Returns a singleton instance of Database.
*
* @param string Database name
* @return Database_Core
*/
public static function instance($name = 'default')
{
if ( ! isset(Database::$instances[$name]))
{
// Load the configuration for this database group
$config = Kohana::config('database.'.$name);
if (is_string($config['connection']))
{
// Parse the DSN into connection array
$config['connection'] = Database::parse_dsn($config['connection']);
}
// Set the driver class name
$driver = 'Database_'.ucfirst($config['connection']['type']);
// Create the database connection instance
Database::$instances[$name] = new $driver($config);
}
return Database::$instances[$name];
}
/**
* Constructs a new Database object
*
* @param array Database config array
* @return Database_Core
*/
protected function __construct(array $config)
{
// Store the config locally
$this->config = $config;
if ($this->config['cache'] !== FALSE)
{
if (is_string($this->config['cache']))
{
// Use Cache library
$this->cache = new Cache($this->config['cache']);
}
elseif ($this->config['cache'] === TRUE)
{
// Use array
$this->cache = array();
}
}
}
public function __destruct()
{
$this->disconnect();
}
/**
* Connects to the database
*
* @return void
*/
abstract public function connect();
/**
* Disconnects from the database
*
* @return void
*/
abstract public function disconnect();
/**
* Sets the character set
*
* @return void
*/
abstract public function set_charset($charset);
/**
* Executes the query
*
* @param string SQL
* @return Database_Result
*/
abstract public function query_execute($sql);
/**
* Escapes the given value
*
* @param mixed Value
* @return mixed Escaped value
*/
abstract public function escape($value);
/**
* List constraints for the given table
*
* @param string Table name
* @return array
*/
abstract public function list_constraints($table);
/**
* List fields for the given table
*
* @param string Table name
* @return array
*/
abstract public function list_fields($table);
/**
* List tables for the given connection (checks for prefix)
*
* @return array
*/
abstract public function list_tables();
/**
* Converts the given DSN string to an array of database connection components
*
* @param string DSN string
* @return array
*/
public static function parse_dsn($dsn)
{
$db = array
(
'type' => FALSE,
'user' => FALSE,
'pass' => FALSE,
'host' => FALSE,
'port' => FALSE,
'socket' => FALSE,
'database' => FALSE
);
// Get the protocol and arguments
list ($db['type'], $connection) = explode('://', $dsn, 2);
if ($connection[0] === '/')
{
// Strip leading slash
$db['database'] = substr($connection, 1);
}
else
{
$connection = parse_url('http://'.$connection);
if (isset($connection['user']))
{
$db['user'] = $connection['user'];
}
if (isset($connection['pass']))
{
$db['pass'] = $connection['pass'];
}
if (isset($connection['port']))
{
$db['port'] = $connection['port'];
}
if (isset($connection['host']))
{
if ($connection['host'] === 'unix(')
{
list($db['socket'], $connection['path']) = explode(')', $connection['path'], 2);
}
else
{
$db['host'] = $connection['host'];
}
}
if (isset($connection['path']) AND $connection['path'])
{
// Strip leading slash
$db['database'] = substr($connection['path'], 1);
}
}
return $db;
}
/**
* Returns the last executed query for this database
*
* @return string
*/
public function last_query()
{
return $this->last_query;
}
/**
* Executes the given query, returning the cached version if enabled
*
* @param string SQL query
* @return Database_Result
*/
public function query($sql)
{
// Start the benchmark
$start = microtime(TRUE);
if (is_array($this->cache))
{
$hash = $this->query_hash($sql);
if (isset($this->cache[$hash]))
{
// Use cached result
$result = $this->cache[$hash];
// It's from cache
$sql .= ' [CACHE]';
}
else
{
// No cache, execute query and store in cache
$result = $this->cache[$hash] = $this->query_execute($sql);
}
}
else
{
// Execute the query, cache is off
$result = $this->query_execute($sql);
}
// Stop the benchmark
$stop = microtime(TRUE);
if ($this->config['benchmark'] === TRUE)
{
// Benchmark the query
Database::$benchmarks[] = array('query' => $sql, 'time' => $stop - $start, 'rows' => count($result));
}
return $result;
}
/**
* Performs the query on the cache (and caches it if it's not found)
*
* @param string query
* @param int time-to-live (NULL for Cache default)
* @return Database_Cache_Result
*/
public function query_cache($sql, $ttl)
{
if ( ! $this->cache instanceof Cache)
{
throw new Database_Exception('Database :name has not been configured to use the Cache library.');
}
// Start the benchmark
$start = microtime(TRUE);
$hash = $this->query_hash($sql);
if (($data = $this->cache->get($hash)) !== NULL)
{
// Found in cache, create result
$result = new Database_Cache_Result($data, $sql, $this->config['object']);
// It's from the cache
$sql .= ' [CACHE]';
}
else
{
// Run the query and return the full array of rows
$data = $this->query_execute($sql)->as_array(TRUE);
// Set the Cache
$this->cache->set($hash, $data, NULL, $ttl);
// Create result
$result = new Database_Cache_Result($data, $sql, $this->config['object']);
}
// Stop the benchmark
$stop = microtime(TRUE);
if ($this->config['benchmark'] === TRUE)
{
// Benchmark the query
Database::$benchmarks[] = array('query' => $sql, 'time' => $stop - $start, 'rows' => count($result));
}
return $result;
}
/**
* Generates a hash for the given query
*
* @param string SQL query string
* @return string
*/
protected function query_hash($sql)
{
return sha1(str_replace("\n", ' ', trim($sql)));
}
/**
* Clears the internal query cache.
*
* @param mixed clear cache by SQL statement, NULL for all, or TRUE for last query
* @param integer Type of cache to clear, Database::CROSS_REQUEST or Database::PER_REQUEST
* @return Database
*/
public function clear_cache($sql = NULL, $type = NULL)
{
if ($this->cache instanceof Cache AND ($type == NULL OR $type == Database::CROSS_REQUEST))
{
// Using cross-request Cache library
if ($sql === TRUE)
{
$this->cache->delete($this->query_hash($this->last_query));
}
elseif (is_string($sql))
{
$this->cache->delete($this->query_hash($sql));
}
else
{
$this->cache->delete_all();
}
}
elseif (is_array($this->cache) AND ($type == NULL OR $type == Database::PER_REQUEST))
{
// Using per-request memory cache
if ($sql === TRUE)
{
unset($this->cache[$this->query_hash($this->last_query)]);
}
elseif (is_string($sql))
{
unset($this->cache[$this->query_hash($sql)]);
}
else
{
$this->cache = array();
}
}
}
/**
* Quotes the given value
*
* @param mixed value
* @return mixed
*/
public function quote($value)
{
if ( ! $this->config['escape'])
return $value;
if ($value === NULL)
{
return 'NULL';
}
elseif ($value === TRUE)
{
return 'TRUE';
}
elseif ($value === FALSE)
{
return 'FALSE';
}
elseif (is_int($value))
{
return (int) $value;
}
elseif ($value instanceof Database_Expression)
{
return (string) $value;
}
return '\''.$this->escape($value).'\'';
}
/**
* Quotes a table, adding the table prefix
* Reserved characters not allowed in table names for the builder are [ .*] (space, dot, asterisk)
*
* @param string|array table name or array - 'users u' or array('u' => 'users') both valid
* @param string table alias
* @return string
*/
public function quote_table($table, $alias = NULL)
{
if (is_array($table))
{
// Using array('u' => 'user')
list($alias, $table) = each($table);
}
elseif (strpos(' ', $table) !== FALSE)
{
// Using format 'user u'
list($table, $alias) = explode(' ', $table);
}
if ($table instanceof Database_Expression)
{
if ($alias)
{
if ($this->config['escape'])
{
$alias = $this->quote.$alias.$this->quote;
}
return $table.' AS '.$alias;
}
return (string) $table;
}
if ($this->config['table_prefix'])
{
$table = $this->config['table_prefix'].$table;
}
if ($alias)
{
if ($this->config['escape'])
{
$table = $this->quote.$table.$this->quote;
$alias = $this->quote.$alias.$this->quote;
}
return $table.' AS '.$alias;
}
if ($this->config['escape'])
{
$table = $this->quote.$table.$this->quote;
}
return $table;
}
/**
* Quotes column or table.column, adding the table prefix if necessary
* Reserved characters not allowed in table names for the builder are [ .*] (space, dot, asterisk)
* Complex column names must have table/columns in double quotes, e.g. array('mycount' => 'COUNT("users.id")')
*
* @param string|array column name or array('u' => 'COUNT("*")')
* @param string column alias
* @return string
*/
public function quote_column($column, $alias = NULL)
{
if ($column === '*')
return $column;
if (is_array($column))
{
list($alias, $column) = each($column);
}
if ($column instanceof Database_Expression)
{
if ($alias)
{
if ($this->config['escape'])
{
$alias = $this->quote.$alias.$this->quote;
}
return $column.' AS '.$alias;
}
return (string) $column;
}
if ($this->config['table_prefix'] AND strpos($column, '.') !== FALSE)
{
if (strpos($column, '"') !== FALSE)
{
// Find "table.column" and replace them with "[prefix]table.column"
$column = preg_replace('/"([^.]++)\.([^"]++)"/', '"'.$this->config['table_prefix'].'$1.$2"', $column);
}
else
{
// Attach table prefix if table.column format
$column = $this->config['table_prefix'].$column;
}
}
if ($this->config['escape'])
{
if (strpos($column, '"') === FALSE)
{
// Quote the column
$column = $this->quote.$column.$this->quote;
}
elseif ($this->quote !== '"')
{
// Replace double quotes
$column = str_replace('"', $this->quote, $column);
}
// Replace . with "."
$column = str_replace('.', $this->quote.'.'.$this->quote, $column);
// Unescape any asterisks
$column = str_replace($this->quote.'*'.$this->quote, '*', $column);
if ($alias)
{
// Quote the alias
return $column.' AS '.$this->quote.$alias.$this->quote;
}
return $column;
}
// Strip double quotes
$column = str_replace('"', '', $column);
if ($alias)
return $column.' AS '.$alias;
return $column;
}
/**
* Get the table prefix
*
* @param string Optional new table prefix to set
* @return string
*/
public function table_prefix($new_prefix = NULL)
{
$prefix = $this->config['table_prefix'];
if ($new_prefix !== NULL)
{
// Set a new prefix
$this->config['table_prefix'] = $new_prefix;
}
return $prefix;
}
/**
* Fetches SQL type information about a field, in a generic format.
*
* @param string field datatype
* @return array
*/
protected function sql_type($str)
{
static $sql_types;
if ($sql_types === NULL)
{
// Load SQL data types
$sql_types = Kohana::config('sql_types');
}
$str = trim($str);
if (($open = strpos($str, '(')) !== FALSE)
{
// Closing bracket
$close = strpos($str, ')', $open);
// Length without brackets
$length = substr($str, $open + 1, $close - 1 - $open);
// Type without the length
$type = substr($str, 0, $open).substr($str, $close + 1);
}
else
{
// No length
$type = $str;
}
if (empty($sql_types[$type]))
throw new Database_Exception('Undefined field type :type', array(':type' => $str));
// Fetch the field definition
$field = $sql_types[$type];
$field['sql_type'] = $type;
if (isset($length))
{
// Add the length to the field info
$field['length'] = $length;
}
return $field;
}
} // End Database

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,83 @@
<?php defined('SYSPATH') or die('No direct script access.');
/**
* Cached database result.
*
* $Id: Database_Cache_Result.php 4679 2009-11-10 01:45:52Z isaiah $
*
* @package Kohana
* @author Kohana Team
* @copyright (c) 2008-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class Database_Cache_Result_Core extends Database_Result {
/**
* Result data (array of rows)
* @var array
*/
protected $data;
public function __construct($data, $sql, $return_objects)
{
$this->data = $data;
$this->sql = $sql;
$this->total_rows = count($data);
$this->return_objects = $return_objects;
}
public function __destruct()
{
// Not used
}
public function as_array($return = FALSE)
{
// Return arrays rather than objects
$this->return_objects = FALSE;
if ( ! $return )
{
// Return this result object
return $this;
}
// Return the entire array of rows
return $this->data;
}
public function as_object($class = NULL, $return = FALSE)
{
if ($class !== NULL)
throw new Database_Exception('Database cache results do not support object casting');
// Return objects of type $class (or stdClass if none given)
$this->return_objects = TRUE;
return $this;
}
public function seek($offset)
{
if ( ! $this->offsetExists($offset))
return FALSE;
$this->current_row = $offset;
return TRUE;
}
public function current()
{
if ($this->return_objects)
{
// Return a new object with the current row of data
return (object) $this->data[$this->current_row];
}
else
{
// Return an array of the row
return $this->data[$this->current_row];
}
}
} // End Database_Cache_Result

View File

@ -0,0 +1,17 @@
<?php defined('SYSPATH') or die('No direct script access.');
/**
* Database exceptions.
*
* $Id: Database_Exception.php 4679 2009-11-10 01:45:52Z isaiah $
*
* @package Kohana
* @author Kohana Team
* @copyright (c) 2008-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class Database_Exception_Core extends Kohana_Exception {
// Database error code
protected $code = E_DATABASE_ERROR;
} // End Database_Exception

Some files were not shown because too many files have changed in this diff Show More