
=head1 NAME

Nes::Singleton - Single access interface to Nes.

=head1 SYNOPSIS

    use Nes;
    my $nes = Nes::Singleton->new('template.nhtml');

    my $config        = $nes->{'CFG'};
    my $cookies       = $nes->{'cookies'};
    my $session       = $nes->{'session'};
    my $query         = $nes->{'query'};
    my $top_container = $nes->{'top_container'};
    my $container     = $nes->{'container'};
    my $register      = $nes->{'register'}; 

    my $nes_tags = {};
    $nes_tags->{'var_hello'} = 'Hello World!';

    $nes->out(%$nes_tag);

=head1 DESCRIPTION

Is a class for a single access interface to Nes. It aims to simplify the 
use of Nes, through a single instance to access the template that is 
running. Create all the necessary objects and returns an instance of this.

It also allows the template to be executed in different ways, calling 
the Perl script, calling to template or command line.

Nes should be run by calling the template, other methods are 
implemented to facilitate debugging.

It is an object of type singleton:

    Nes::Singleton->new('template.nhtml'); # returns a new instance
    Nes::Singleton->new('other.nhtml');    # returns same instance
    Nes::Singleton->new();                 # returns same instance

In most cases you just need to do this:

    use Nes;
    my $nes = Nes::Singleton->new('template.nhtml');
    my %tags;

    # the things that make your script...
    ...
    # set variables for output
    $tags{'var_hello'} = 'Hello World!';

    # the things that make your script...
    ...
    # send variables to Nes
    $nes->out(%tags);

=head1 Nes::Singleton Diagrams

Nes::Singleton represents the Web page and its elements. Access to the various 
elements is through instances created by Nes::Singleton:

    .--------------------------------------.
    |           Nes::Singleton             |->Nes::Singleton->{'top_container'}
    |  http://example.com/template.nhtml   |  
    |.----------------------------------.  |  
    ||  POST and GET ------------------------>Nes::Singleton->{'query'}
    ||  Cookie ------------------------------>Nes::Singleton->{'cookies'}
    |'----------------------------------'  |
    |.----------------------------------.  |
    ||<html>                            |---->Nes::Singleton->{'container'}
    ||...                               |  | 
    || .-----------------------------.  |  |
    || |{: include ('obj1.nhtml') :} |  |  |  
    || |                             |------->Nes::Singleton->{'container'}
    || |                             |  |  | 
    || '-----------------------------'  |  |
    ||...                               |  | 
    || .-----------------------------.  |  |
    || |{: include ('obj2.nhtml') :} |  |  |
    || |                             |------->Nes::Singleton->{'container'}
    || |                             |  |  |  
    || '-----------------------------'  |  |  
    ||...                               |  |  
    ||</html>                           |  |
    |'----------------------------------'  |
    '--------------------------------------'

Nes::Singleton Object:

    .--------------------.
    |   Nes::Singleton   |
    |--------------------|
    | {'CFG'}            |
    | {'top_container'}  |
    | {'container'}      |
    | {'cookies'}        |
    | {'session'}        |
    | {'query'}          |
    | {'register'}       |
    |--------------------|
    | new()              |
    | add()              |
    | out()              |
    | instance()         |
    '--------------------'

=over 2

=item Nes::Singleton->{'top_container'}

Represents the Web page and all content. It creates a higher level container
for other elements.

=item Nes::Singleton->{'container'}

Represents the HTML, PHP, TXT, etc. content, or other files included in
the template.

=item Nes::Singleton->{'query'}

make:

    use Nes;
    my $nes = Nes::Singleton->new;
    my $q   = $nes->{'query'}->{'q'};

is equivalent to do:

    use CGI;
    my $q = CGI->new;

=item Nes::Singleton->{'cookies'}

Represents the cookies.

=item Nes::Singleton->{'session'}

Represents the user session.

=item Nes::Singleton->{'CFG'}

Represents the settings for the directory containing the Top Container.

=item Nes::Singleton->{'register'}

Represents access to plugins.

=back

Nes Request:

    .-------------------------------------------.
    |         GET or POST HTTP Request          |
    |     http://example.com/template.nhtml     |
    '-------------------------------------------'
                        |
                        v
    .-------------------------------------------.
    |        /cgi-bin/nes/dispatch.cgi          |
    '-------------------------------------------'
                        |
                        v
    .-------------------------------------------.
    |              Nes::Singleton               |
    |-------------------------------------------|
    | new {'CFG'} for this dir                  |
    | new {'top_container '} for template.nhtml |
    '-------------------------------------------'
                        |
                        v
    .-------------------------------------------.
    |     Nes::Singleton->{'top_container'}     |
    |-------------------------------------------|
    | new {'register'}                          |
    | new {'query'}                             |
    | new {'cookies'}                           |
    | new {'session'}                           |
    | new {'container'} for template.nhtml      |
    '-------------------------------------------'             
                        |
                        v
    .-------------------------------------------.
    |       Nes::Singleton->{'container'}       | <---.
    |-------------------------------------------|     |
    | get {: NES 1.0 ... :} line                |     |
    | new {'content_obj'} for this content type |     |
    '-------------------------------------------'     |          
                        |                             |
                        v                             |
    .-------------------------------------------.     |
    |             do Perl scripts               |     |
    |-------------------------------------------|     |
    | Nes::Singleton->out()                     |     |
    '-------------------------------------------'     |
                        |                             |
                        v                             |
    .-------------------------------------------.     |
    | Nes::Singleton->{'container'}->interpret  |     |
    '-------------------------------------------'     |
                        |                             |
                        v                       ( interaction )
             .---------------------.                  |
             | {: include :}   ?   |---[ yes ]--------'
             '---------------------'                         
                        |
                      [ no ]
                        |
                        v
    .-------------------------------------------.
    | print HTTP Headers                        |
    | print the out                             |
    '-------------------------------------------'

Nes Object:

    .------------------------------------------------------------------------------------.
    |                                 | Nes Object |                                     |
    |                                 '------------'                                     |
    | .-----------------------------------.    .---------------------------------------. |
    | |          template.nhtml           |    |              script.pl                | |
    | |-----------------------------------|    |---------------------------------------| |
    | |                                   |--->|                                       | |
    | |    {: Nes 1.0 ('script.pl') :}    |    | Nes::Singleton->new('template.nhtml') | |
    | |                                   |<---|                                       | |
    | '-----------------------------------'    '---------------------------------------' |
    '------------------------------------------------------------------------------------'

Nes Model:

    .----------------------------------------------.
    |                 | Nes Object |               |
    |                 '------------'               |
    | .-------------------.    .-----------------. |
    | |  template.nhtml   |    |    script.pl    | |
    | |-------------------|    |-----------------| |
    | |        _          |--->|    _       _    | |
    | |        |          |<---|    |       |    | |
    | '--------|----------'    '----|-------|----' |
    '----------|--------------------|-------|------'
               |                    |       |
               |                    |       '------------------.
               |                    |                          |
               v                    v                          v
    .----------------------.  .-----------------------.  .------------.
    |                      |  |                       |  |            |
    |  Nes Object Library  |  |  My App Perl Library  |  |    CPAN    |
    |                      |  |                       |  |            |
    '----------------------'  '-----------------------'  '------------'

Nes Data Flow:

    .------------.        .-----------------------.
    |            |        |                       |
    |    DATA    |------->|  My App Perl Library  |
    |            |        |                       |
    '------------'        '-----------------------'
           |                                |
           '--------------------------.     |
    .---------------------------------|-----|-----.
    |                | Nes Object |   |     |     |
    |                '------------'   v     v     |
    | .------------------.    .-----------------. |
    | |  template.nhtml  |<---|    script.pl    | |
    | '------------------'    '-----------------' |
    '----------|----------------------------------'
               v
    .---------------------.
    |         OUT         |
    '---------------------'

=head1 Methods

=head2 new

    use Nes;
    my $nes = Nes::Singleton->new('template.nhtml');

Only require parameter if Nes is executed by CGI.

    http://example.con/perl.cgi

Or command line:

    ./perl.cgi

The parameter is ignored if executed Nes by template.

    http://example.con/template.nhtml

Nes should be run by calling the template, other methods are 
implemented to facilitate debugging.

=head2 out

In the parameter we pass a copy of hash (%$hash) with the data we want
to replace in the template.

    my $nes_tags = {};
    $nes_tags->{'hello'} = 'Hello World!';
    $nes->out(%$nes_tag);

    ./.

    my %nes_tags;
    $nes_tags{'hello'} = 'Hello World!';
    $nes->out(%nes_tag);

The method 'out' does not exit script or immediately print values, 
your script can continue after call to out, but for clarity it is 
recommended to include at the end of script.

This will work:

    ...
    $nes->out(%$nes_tag);
    &foo($bar);
    ...

For clarity use this:

    ...
    &foo($bar);
    $nes->out(%$nes_tag);
    ...

=head2 add

Added Tags without sending out. If you template:

    {: NES 1.0 ('myscript1.pl','myscript2.pl') :}

If myscript1 and myscript2 defined Tags, mysqcript1 should have:

    $nes->add(%tags);

And myscript2:

    $nes->out(%tags);

If you call to out method in myscript1, the tags of myscript2 never be replaced. 
If you not call to out method in last script, the Tags never be replaced.

The routine use of the add method is in creating plugin.

=head1 .nes.cfg

You .nes.cfg contains:

    private_key   = pass3
    myscript_var1 = 50

Then you can access:

    use Nes;
    my $nes    = Nes::Singleton->new('template.nhtml');
    my $config = $nes->{'CFG'};

    my $var  = $config->{'myscript_var1'};
    my $pkey = $config->{'private_key'};

    # Global configuration
    my $pdir = $config->{'plugin_top_dir'};

=head1 Session

    my $nes     = Nes::Singleton->new();
    my $session = $nes->{'session'};

    # Create session:
    $session->create($user, $expire);

    # Get session:
    $user = $session->{'user'};

    # Delete session:
    $session->del;

=head1 Query

    use Nes;
    my $nes   = Nes::Singleton->new('template.nhtml');
    my $query = $nes->{'query'};
    my $q     = $query->{'q'};

Nes::Singleton->{'query'}->{'q'} is equivalent to do:

    use CGI;
    my $q = CGI->new;

In addition to GET or POST with Nes::Singleton->{'query'} we pick 
parameters of Nes Objects in the following format:

    objectname_param_number

For our example the name of the object is lucky.nhtml, the extension 
is ignored, then the first parameter:

    Nes::Singleton->{'query'}->{'q'}{'lucky_param_1'}

The object name is:

    my $obj = Nes::Singleton->{'query'}->{'q'}{'obj_param_0'};
    my $par = Nes::Singleton->{'query'}->{'q'}{$obj.'_param_1'};

The following variables are available in .nes.cfg for POST control:
                     
    max_post   = 512  # Max kB. maximum size of POST.
    max_upload = 2048 # Max kB. maximum size of the upload, 0 none
    tmp_upload = 512  # In big upload, memory consumption is high,
                      # this defined from that kB. using a temporary
                      # file in the upload, preventing these are 
                      # loaded into memory. 
                      # * If tmp_upload is 0 or is greater than max_post, 
                      # max_upload limit will be equal to max_post. Therefore, 
                      # max_upload to take value, tmp_upload to be equal to or 
                      # less than max_post.                      

For disable uploads, put this in you .nes.cfg:

    max_upload = 0

=head2 Query Methods

Access to query is via a patched version of CGI::Minimal (ver. 1.29). Most 
of the methods are accessible by creating an instance of CGI. No need to 
create a CGI object with new method, it automatically creates by Nes:

    use Nes;
    my $nes = Nes::Singleton->new;
    my $cgi = $nes->{'query'}->{'CGI'};

In this way we can access the methods of CGI::Minimal:

    ...
    $param = $cgi->param('param');
    ...

See: http://search.cpan.org/perldoc?CGI::Minimal

Our patched version includes temporary files and other modifications and 
define new methods and access to the most common:

=over 2

=item param;

Called without arguments, it returns the list of all defined form fields in 
the same order they appear in the data from the user agent.

If you include as parameter the name of the field, it returns the value 
(or an array, if you have multiple). If there is more than one value, the 
values are returned in the same order they appeared in the data from user agent.

Same as CGI::Minimal->param. See: http://search.cpan.org/perldoc?CGI::Minimal

=item get_upload_buffer

Get te upload content by buffer:

    use Nes;
    my $nes = Nes::Singleton->new;
    my $query = $nes->{'query'};
    ...
    while ( $query->get_upload_buffer('field_name',\$buffer) ) {
        print $fh $buffer;
    }
    ...

=item get_upload_name

Get the file name of upload by the field:

    use Nes;
    my $nes = Nes::Singleton->new;
    my $query = $nes->{'query'};
    ...
    $file_name = $query->get_upload_name('field_name');

=item get_upload_fh

Get the file handle of upload:

    use Nes;
    my $nes = Nes::Singleton->new;
    my $query = $nes->{'query'};
    ...
    $fh = $query->get_upload_fh('field_name');

=item upload_is_tmp

Return true if upload is in tmp file:

    $in_tmp_file = $query->upload_is_tmp('field_name');

Depending on your max_post, tmp_upload and max_upload. The upload can be in 
a temporary file or memory.

This will always work, although the upload is in memory:

    $fh = $query->get_upload_fh('field_name');
or:
    $query->get_upload_buffer('field_name',\$buffer)

A little faster:

    if ( ! $query->upload_is_tmp('field_name') ) {
        $content_upload = $query->{'q'}{'field_name'};
    }

If the upload is in memory:

    $file_name = $query->{'q'}{'field_name'};

else:

    $content_upload = $query->{'q'}{'field_name'};

=item upload_max_size

Return true if it has exceeded the maximum limit of max_upload .nes.cfg var. 

=item post_max_size

Return true if it has exceeded the maximum limit of max_post .nes.cfg var. 

=item get_buffer_raw

Returns a copy of the raw form data to max_post:

    $post_data_raw = $query->get_buffer;

=item get_buffer

Returns a copy of the raw form data, including temporary files:

    while ( my $buffer = $query->get_buffer ) {
        $post_data_raw .= $buffer;
    }

=item get

Get a field:

    $field = $query->{'q'}{'field_name'}
Same:
    $field = $query->get('field_name');

=item set

Set a field:

    $query->{'q'}{'field_name'} = 'value';
Same:
    $query->set('field_name', 'value');  

=item del

Undef field:

    $query->del('field_name');

=item url_encode

Returns URL encoding of input string.

=item url_decode

Returns URL decoding of input string.

=back

=head1 AUTHOR

Skriptke: Enrique F. Castanon

=head1 VERSION

Version 1.04

=head1 COPYRIGHT

Copyright (c) Enrique F. Castanon Barbero. All rights reserved.

Copyright (c) Benjamin Franz. All rights reserved. (CGI::Minimal)

=head1 LICENSE

This program is free software; you can redistribute it
and/or modify it under the same terms and conditions as
GNU Public License (GPL).

This means that you can, at your option, redistribute it and/or 
modify it under either the terms the GNU Public License (GPL), 
or under the Perl Artistic License.

See http://dev.perl.org/licenses/

=head1 DISCLAIMER

THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE.

Use of this software in any way or in any form, source or binary,
is not allowed in any country which prohibits disclaimers of any
implied warranties of merchantability or fitness for a particular
purpose or any disclaimers of a similar nature.

IN NO EVENT SHALL I BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
SPECIAL, INCIDENTAL,  OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OF THIS SOFTWARE AND ITS DOCUMENTATION (INCLUDING, BUT NOT
LIMITED TO, LOST PROFITS) EVEN IF I HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE

=head1 SEE ALSO

Sample to use Nes; L<http://nes.sourceforge.net/>, 
L<Nes>, L<Nes::Tutorial>, L<Nes::nes.cfg>, L<CGI::Minimal>

=cut

