+This module handles unpacking of CGI parameters. It also gives
+information about the request, such as whether or not it was done via AJAX,
+or the requested content type.
+
+ use SL::Request;
+
+ # read cgi input depending on request type, unflatten and recode
+ $::request->read_cgi_input($target_hash_ref);
+
+ # $hashref and $new_hashref should be identical
+ my $new_arrayref = flatten($hashref);
+ my $new_hashref = unflatten($new_arrayref);
+
+ # Handle AJAX requests differently than normal requests:
+ if ($::request->is_ajax) {
+ $controller->render('json-mask', { type => 'json' });
+ } else {
+ $controller->render('full-mask');
+ }
+
+=head1 DESCRIPTION
+
+This module provides information about the request made by the
+browser.
+
+It also handles flattening and unflattening of data for request
+roundtrip purposes. kivitendo uses the format as described below:
+
+=over 4
+
+=item Hashes
+
+Hash entries will be connected with a dot (C<.>). A simple hash like this
+
+ order => {
+ item => 2,
+ customer => 5
+ }
+
+will be serialized to
+
+ [ order.item => 2 ],
+ [ order.customer => 5 ],
+
+=item Arrays
+
+Arrays will be marked by empty brackets (C<[]>). A hash like this
+
+ selected_id => [ 2, 6, 8, 9 ]
+
+will be flattened to
+
+ [ selected_id[] => 2 ],
+ [ selected_id[] => 6 ],
+ [ selected_id[] => 8 ],
+ [ selected_id[] => 9 ],
+
+Since this will produce identical keys, the resulting flattened list can not be
+used as a hash. It is however very easy to use this in a template to generate
+input:
+
+ [% FOREACH id = selected_ids %]
+ <input type="hidden" name="selected_id[]" value="[% id | html %]">
+ [% END %]
+
+=item Nested structures
+
+A special version of this are nested hashes in an array, which is very common.
+The combined operator (C<[].>) will be used. As a special case, every time a new
+array slice is started, the special convention (C<[+].>) will be used. Again this
+is because it's easy to write a template with it.
+
+So this
+
+ order => {
+ orderitems => [
+ {
+ id => 1,
+ part => 15
+ },
+ {
+ id => 2,
+ part => 7
+ },
+ ]
+ }
+
+will be
+
+ [ order.orderitems[+].id => 1 ],
+ [ order.orderitems[].part => 15 ],
+ [ order.orderitems[+].id => 2 ],
+ [ order.orderitems[].part => 7 ],
+
+=item Limitations
+
+ The format currently does have certain limitations when compared to other
+ serialization formats.
+
+=over 4
+
+=item Order
+
+The order of serialized values matters to reconstruct arrays properly. This
+should rarely be a problem if you just flatten and dump into a url or a field
+of hiddens.
+
+=item Empty Keys
+
+The current implementation of flatten does produce correct serialization of
+empty keys, but unflatten is unable to resolve these. Do no use C<''> or
+C<undef> as keys. C<0> is fine.
+
+=item Key Escaping
+
+You cannot use the tokens C<[]>, C<[+]> and C<.> in keys. No way around it.
+
+=item Sparse Arrays
+
+It is not possible to serialize something like
+
+ sparse_array => do { my $sa = []; $sa[100] = 1; $sa },
+
+This is a feature, as perl doesn't do well with very large arrays.
+
+=item Recursion
+
+There is currently no support nor prevention for flattening a circular structure.
+
+=item Custom Delimiter
+
+No support for other delimiters, sorry.
+
+=item Other References
+
+No support for globs, scalar refs, code refs, filehandles and the like. These will die.
+
+=back
+
+=back
+
+=head1 FUNCTIONS
+
+=over 4
+
+=item C<flatten HASHREF [ ARRAYREF ]>
+
+This function will flatten the provided hash ref into the provided array ref.
+The array ref may be non empty, but will be changed in this case.
+
+The return value is the flattened array ref.
+
+=item C<unflatten ARRAYREF [ HASHREF ]>
+
+This function will parse the array ref, and will store the contents into the hash ref. The hash ref may be non empty, in this case any new keys will override the old ones only on leafs with same type. Type changes on a node will die.
+
+=item C<is_ajax>
+
+Returns trueish if the request is an XML HTTP request, also known as
+an 'AJAX' request.
+
+=item C<type>
+
+Returns the requested content type (either C<html>, C<js> or C<json>).
+
+=item C<layout>
+
+Set and retrieve the layout object for the current request. Must be an instance
+of L<SL::Layout::Base>. Defaults to an instance of L<SL::Layout::None>.
+
+For more information about layouts, see L<SL::Layout::Dispatcher>.
+
+=item C<cache $topic[, $default ]>
+
+Caches an item for the duration of the request. C<$topic> must be an
+index name referring to the thing to cache. It is used for retrieving
+it later on. If C<$topic> doesn't start with C<::> then the caller's
+package name is prepended to the topic. For example, if the a from
+package C<SL::StuffedStuff> calls with topic = C<get_stuff> then the
+actual key will be C<::SL::StuffedStuff::get_stuff>.
+
+If no item exists in the cache for C<$topic> then it is created and
+its initial value is set to C<$default>. If C<$default> is not given
+(undefined) then a new, empty hash reference is created.
+
+Returns the cached item.
+
+=item C<post_data>
+
+If the client sends data in the request body with the content type of
+either C<application/json> or C<multipart/form-data>, the content will
+be stored in the global request object, too. It can be retrieved via
+the C<post_data> function.
+
+For content type C<multipart/form-data> the same data is additionally
+stored in the global C<$::form> instance, potentially overwriting
+parameters given in the URL. This is done primarily for compatibility
+purposes with existing code that expects all parameters to be present
+in C<$::form>.
+
+For content type C<application/json> the data is only available in
+C<$::request>. The reason is that the top-level data in a JSON
+documents doesn't have to be an object which could be mapped to the
+hash C<$::form>. Instead, the top-level data can also be an
+array. Additionally keeping the namespaces of URL and POST parameters
+separate is cleaner and allows for fewer accidental conflicts.