Merge branch 'develop' of git://github.com/EllisLab/CodeIgniter into develop
diff --git a/system/core/Router.php b/system/core/Router.php
index 5bc0530..e8addf9 100644
--- a/system/core/Router.php
+++ b/system/core/Router.php
@@ -371,10 +371,48 @@
 			$key = str_replace(array(':any', ':num'), array('.+', '[0-9]+'), $key);
 
 			// Does the RegEx match?
-			if (preg_match('#^'.$key.'$#', $uri))
+			if (preg_match('#^'.$key.'$#', $uri, $matches))
 			{
-				// Do we have a back-reference?
-				if (strpos($val, '$') !== FALSE && strpos($key, '(') !== FALSE)
+				// Are we using callbacks to process back-references?
+				if ( ! is_string($val) && is_callable($val))
+				{
+					// Remove the original string from the matches array.
+					array_shift($matches);
+
+					// Get the match count.
+					$match_count = count($matches);
+
+					// Determine how many parameters the callback has.
+					$reflection = new ReflectionFunction($val);
+					$param_count = $reflection->getNumberOfParameters();
+
+					// Are there more parameters than matches?
+					if ($param_count > $match_count)
+					{
+						// Any params without matches will be set to an empty string.
+						$matches = array_merge($matches, array_fill($match_count, $param_count - $match_count, ''));
+
+						$match_count = $param_count;
+					}
+
+					// Get the parameters so we can use their default values.
+					$params = $reflection->getParameters();
+
+					for ($m = 0; $m < $match_count; $m++)
+					{
+						// Is the match empty and does a default value exist?
+						if (empty($matches[$m]) && $params[$m]->isDefaultValueAvailable())
+						{
+							// Substitute the empty match for the default value.
+							$matches[$m] = $params[$m]->getDefaultValue();
+						}
+					}
+
+					// Execute the callback using the values in matches as its parameters.
+					$val = call_user_func_array($val, $matches);
+				}
+				// Are we using the default routing method for back-references?
+				elseif (strpos($val, '$') !== FALSE && strpos($key, '(') !== FALSE)
 				{
 					$val = preg_replace('#^'.$key.'$#', $val, $uri);
 				}
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index d3cebc7..c87aebd 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -145,7 +145,11 @@
    -  Added PDO support for ``create_database()``, ``drop_database()`` and ``drop_table()`` in :doc:`Database Forge <database/forge>`.
    -  Added ``unbuffered_row()`` method for getting a row without prefetching whole result (consume less memory).
    -  Added PDO support for ``list_fields()`` in :doc:`Database Results <database/results>`.
+<<<<<<< HEAD
+   -  Added capability for packages to hold database.php config files
+=======
    -  Added capability for packages to hold *database.php* config files
+>>>>>>> a7001e968a4791312391eb245ad84888893cda8f
    -  Added subdrivers support (currently only used by PDO).
    -  Added MySQL client compression support.
    -  Added encrypted connections support (for *mysql*, *sqlsrv* and PDO with *sqlsrv*).
@@ -224,6 +228,25 @@
 -  Core
 
    -  Changed private methods in the :doc:`URI Library <libraries/uri>` to protected so MY_URI can override them.
+<<<<<<< HEAD
+   -  Removed CI_CORE boolean constant from CodeIgniter.php (no longer Reactor and Core versions).
+   -  Added method get_vars() to the :doc:`Loader Library <libraries/loader>` to retrieve all variables loaded with $this->load->vars().
+   -  is_loaded() function from system/core/Commons.php now returns a reference.
+   -  $config['rewrite_short_tags'] now has no effect when using PHP 5.4 as *<?=* will always be available.
+   -  Added method() to the :doc:`Input Library <libraries/input>` to retrieve $_SERVER['REQUEST_METHOD'].
+   -  Modified valid_ip() to use PHP's filter_var() in the :doc:`Input Library <libraries/input>`.
+   -  Added support for HTTP-Only cookies with new config option ``cookie_httponly`` (default FALSE).
+   -  Renamed method _call_hook() to call_hook() in the :doc:`Hooks Library <general/hooks>`.
+   -  Added get_content_type() method to the :doc:`Output Library <libraries/output>`.
+   -  Added get_mimes() function to system/core/Commons.php to return the config/mimes.php array.
+   -  Added a second argument to set_content_type() in the :doc:`Output Library <libraries/output>` that allows setting the document charset as well.
+   -  $config['time_reference'] now supports all timezone strings supported by PHP.
+   -  Added support for HTTP code 303 ("See Other") in set_status_header().
+   -  Changed :doc:`Config Library <libraries/config>` method site_url() to accept an array as well.
+   -  Added method ``strip_image_tags()`` to the :doc:`Security Library <libraries/security>`.
+   -  Changed ``_exception_handler()`` to respect php.ini 'display_errors' setting.
+   -  Added possibility to route requests using callback methods.
+=======
    -  Removed ``CI_CORE`` boolean constant from *CodeIgniter.php* (no longer Reactor and Core versions).
    -  :doc:`Loader Library <libraries/loader>` changes include:
 	 -  Added method ``get_vars()`` to the Loader to retrieve all variables loaded with ``$this->load->vars()``.
@@ -252,6 +275,8 @@
 	 -  Added method ``strip_image_tags()``.
 	 -  Added ``$config['csrf_regeneration']``, which makes token regeneration optional.
 	 -  Added ``$config['csrf_exclude_uris']``, which allows you list URIs which will not have the CSRF validation methods run.
+>>>>>>> a7001e968a4791312391eb245ad84888893cda8f
+   -  Added possibility to route requests using callbacks.
 
 Bug fixes for 3.0
 ------------------
diff --git a/user_guide_src/source/general/routing.rst b/user_guide_src/source/general/routing.rst
index c039370..144f129 100644
--- a/user_guide_src/source/general/routing.rst
+++ b/user_guide_src/source/general/routing.rst
@@ -111,6 +111,17 @@
 
 You can also mix and match wildcards with regular expressions.
 
+Callbacks
+=========
+
+If you are using PHP >= 5.3 you can use callbacks in place of the normal routing
+rules to process the back-references. Example::
+
+	$route['products/([a-z]+)/edit/(\d+)'] = function ($product_type, $id)
+	{
+		return "catalog/product_edit/" . strtolower($product_type) . "/" . $id;
+	};
+
 Reserved Routes
 ===============