minor doc improvements
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Helper.pm
index 4787359..331de63 100644 (file)
@@ -2,6 +2,7 @@ package Catalyst::Helper;
 
 use strict;
 use base 'Class::Accessor::Fast';
+use Config;
 use File::Spec;
 use File::Path;
 use IO::File;
@@ -60,36 +61,47 @@ sub mk_app {
     # Needs to be here for PAR
     require Catalyst;
 
-    return 0 if $name =~ /[^\w\:]/;
+    if ( $name =~ /[^\w\:]/ ) {
+        warn "Error: Invalid application name.\n";
+        return 0;
+    }
     $self->{name} = $name;
     $self->{dir}  = $name;
     $self->{dir} =~ s/\:\:/-/g;
     $self->{script}    = File::Spec->catdir( $self->{dir}, 'script' );
     $self->{appprefix} = Catalyst::Utils::appprefix($name);
-    $self->{startperl} = '#!/usr/bin/perl -w';
+    $self->{startperl} = "#!$Config{perlpath} -w";
     $self->{scriptgen} = $Catalyst::CATALYST_SCRIPT_GEN || 4;
     $self->{author}    = $self->{author} = $ENV{'AUTHOR'}
       || eval { @{ [ getpwuid($<) ] }[6] }
       || 'Catalyst developer';
 
-    unless ( $self->{scripts} ) {
+    my $gen_scripts  = ( $self->{makefile} ) ? 0 : 1;
+    my $gen_makefile = ( $self->{scripts} )  ? 0 : 1;
+    my $gen_app = ( $self->{scripts} || $self->{makefile} ) ? 0 : 1;
+
+    if ($gen_app) {
         $self->_mk_dirs;
+        $self->_mk_config;
         $self->_mk_appclass;
-        $self->_mk_build;
-        $self->_mk_makefile;
+        $self->_mk_rootclass;
         $self->_mk_readme;
         $self->_mk_changes;
         $self->_mk_apptest;
         $self->_mk_images;
         $self->_mk_favicon;
-        $self->_mk_package;
     }
-    $self->_mk_cgi;
-    $self->_mk_fastcgi;
-    $self->_mk_server;
-    $self->_mk_test;
-    $self->_mk_create;
-    return 1;
+    if ($gen_makefile) {
+        $self->_mk_makefile;
+    }
+    if ($gen_scripts) {
+        $self->_mk_cgi;
+        $self->_mk_fastcgi;
+        $self->_mk_server;
+        $self->_mk_test;
+        $self->_mk_create;
+    }
+    return $self->{dir};
 }
 
 =head3 mk_component
@@ -106,7 +118,7 @@ sub mk_component {
     $self->{author} = $self->{author} = $ENV{'AUTHOR'}
       || eval { @{ [ getpwuid($<) ] }[6] }
       || 'A clever guy';
-    $self->{base} = File::Spec->catdir( $FindBin::Bin, '..' );
+    $self->{base} ||= File::Spec->catdir( $FindBin::Bin, '..' );
     unless ( $_[0] =~ /^(?:model|view|controller)$/i ) {
         my $helper = shift;
         my @args   = @_;
@@ -133,13 +145,15 @@ sub mk_component {
         $type              = 'M' if $type =~ /model/i;
         $type              = 'V' if $type =~ /view/i;
         $type              = 'C' if $type =~ /controller/i;
-        $type              = $self->{long_type} unless $self->{short};
-        $self->{type}      = $type;
-        $self->{name}      = $name;
-        $self->{class}     = "$app\::$type\::$name";
+        my $appdir = File::Spec->catdir( split /\:\:/, $app );
+        my $test_path =
+          File::Spec->catdir( $FindBin::Bin, '..', 'lib', $appdir, 'C' );
+        $type = $self->{long_type} unless -d $test_path;
+        $self->{type}  = $type;
+        $self->{name}  = $name;
+        $self->{class} = "$app\::$type\::$name";
 
         # Class
-        my $appdir = File::Spec->catdir( split /\:\:/, $app );
         my $path =
           File::Spec->catdir( $FindBin::Bin, '..', 'lib', $appdir, $type );
         my $file = $name;
@@ -217,7 +231,10 @@ sub mk_file {
     my ( $self, $file, $content ) = @_;
     if ( -e $file ) {
         print qq/ exists "$file"\n/;
-        return 0 unless ( $self->{'.newfiles'} || $self->{scripts} );
+        return 0
+          unless ( $self->{'.newfiles'}
+            || $self->{scripts}
+            || $self->{makefile} );
         if ( $self->{'.newfiles'} ) {
             if ( my $f = IO::File->new("< $file") ) {
                 my $oldcontent = join( '', (<$f>) );
@@ -252,13 +269,12 @@ sub next_test {
         $self->{prefix} = $prefix;
         $prefix         = lc $prefix;
         $prefix =~ s/-/\//g;
-        $self->{uri} = $prefix;
+        $self->{uri} = "/$prefix";
     }
     my $dir  = $self->{test_dir};
-    my $type = $self->{type};
-    $dir = File::Spec->catdir( $dir, $type );
+    my $type = lc $self->{type};
     $self->mk_dir($dir);
-    return File::Spec->catfile( $dir, $tname );
+    return File::Spec->catfile( $dir, "$type\_$tname" );
 }
 
 =head3 render_file
@@ -296,17 +312,6 @@ sub _mk_dirs {
     $self->{t} = File::Spec->catdir( $self->{dir}, 't' );
     $self->mk_dir( $self->{t} );
 
-    if ( $self->{short} ) {
-        $self->mk_dir( File::Spec->catdir( $self->{t}, 'M' ) );
-        $self->mk_dir( File::Spec->catdir( $self->{t}, 'V' ) );
-        $self->mk_dir( File::Spec->catdir( $self->{t}, 'C' ) );
-    }
-    else {
-        $self->mk_dir( File::Spec->catdir( $self->{t}, 'Model' ) );
-        $self->mk_dir( File::Spec->catdir( $self->{t}, 'View' ) );
-        $self->mk_dir( File::Spec->catdir( $self->{t}, 'Controller' ) );
-    }
-
     $self->{class} = File::Spec->catdir( split( /\:\:/, $self->{name} ) );
     $self->{mod} = File::Spec->catdir( $self->{lib}, $self->{class} );
     $self->mk_dir( $self->{mod} );
@@ -327,6 +332,9 @@ sub _mk_dirs {
         $self->{c} = File::Spec->catdir( $self->{mod}, 'Controller' );
         $self->mk_dir( $self->{c} );
     }
+    my $name = $self->{name};
+    $self->{rootname} =
+      $self->{short} ? "$name\::C::Root" : "$name\::Controller::Root";
     $self->{base} = File::Spec->rel2abs( $self->{dir} );
 }
 
@@ -336,16 +344,33 @@ sub _mk_appclass {
     $self->render_file( 'appclass', "$mod.pm" );
 }
 
-sub _mk_build {
+sub _mk_rootclass {
     my $self = shift;
-    my $dir  = $self->{dir};
-    $self->render_file( 'build', "$dir\/Build.PL" );
+    $self->render_file( 'rootclass',
+        File::Spec->catfile( $self->{c}, "Root.pm" ) );
 }
 
 sub _mk_makefile {
     my $self = shift;
-    my $dir  = $self->{dir};
+    $self->{path} = File::Spec->catfile( 'lib', split( '::', $self->{name} ) );
+    $self->{path} .= '.pm';
+    my $dir = $self->{dir};
     $self->render_file( 'makefile', "$dir\/Makefile.PL" );
+
+    if ( $self->{makefile} ) {
+
+        # deprecate the old Build.PL file when regenerating Makefile.PL
+        $self->_deprecate_file(
+            File::Spec->catdir( $self->{dir}, 'Build.PL' ) );
+    }
+}
+
+sub _mk_config {
+    my $self      = shift;
+    my $dir       = $self->{dir};
+    my $appprefix = $self->{appprefix};
+    $self->render_file( 'config',
+        File::Spec->catfile( $dir, "$appprefix.yml" ) );
 }
 
 sub _mk_readme {
@@ -444,12 +469,25 @@ sub _mk_favicon {
 
 }
 
-sub _mk_package {
-    my $self      = shift;
-    my $script    = $self->{script};
-    my $appprefix = $self->{appprefix};
-    $self->render_file( 'package', "$script\/$appprefix\_package.pl" );
-    chmod 0700, "$script/$appprefix\_package.pl";
+sub _deprecate_file {
+    my ( $self, $file ) = @_;
+    if ( -e $file ) {
+        my $oldcontent;
+        if ( my $f = IO::File->new("< $file") ) {
+            $oldcontent = join( '', (<$f>) );
+        }
+        my $newfile = $file . '.deprecated';
+        if ( my $f = IO::File->new("> $newfile") ) {
+            binmode $f;
+            print $f $oldcontent;
+            print qq/created "$newfile"\n/;
+            unlink $file;
+            print qq/removed "$file"\n/;
+            return 1;
+        }
+        Catalyst::Exception->throw(
+            message => qq/Couldn't create "$file", "$!"/ );
+    }
 }
 
 =head1 HELPERS
@@ -506,21 +544,23 @@ use warnings;
 # Set flags and add plugins for the application
 #
 #         -Debug: activates the debug mode for very useful log messages
-# Static::Simple: will serve static files from the applications root directory
+#   ConfigLoader: will load the configuration from a YAML file in the
+#                 application's home directory
+# Static::Simple: will serve static files from the application's root 
+#                 directory
 #
-use Catalyst qw/-Debug Static::Simple/;
+use Catalyst qw/-Debug ConfigLoader Static::Simple/;
 
 our $VERSION = '0.01';
 
 #
-# Configure the application
+# Start the application
 #
-__PACKAGE__->config( name => '[% name %]' );
+__PACKAGE__->setup;
 
 #
-# Start the application
+# IMPORTANT: Please look into [% rootname %] for more
 #
-__PACKAGE__->setup;
 
 =head1 NAME
 
@@ -534,11 +574,52 @@ __PACKAGE__->setup;
 
 Catalyst based application.
 
+=head1 SEE ALSO
+
+L<[% rootname %]>, L<Catalyst>
+
+=head1 AUTHOR
+
+[% author %]
+
+=head1 LICENSE
+
+This library is free software, you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
+
+1;
+__rootclass__
+package [% rootname %];
+
+use strict;
+use warnings;
+use base 'Catalyst::Controller';
+
+#
+# Sets the actions in this controller to be registered with no prefix
+# so they function identically to actions created in MyApp.pm
+#
+__PACKAGE__->config->{namespace} = '';
+
+=head1 NAME
+
+[% rootname %] - Root Controller for this Catalyst based application
+
+=head1 SYNOPSIS
+
+See L<[% name %]>.
+
+=head1 DESCRIPTION
+
+Root Controller for this Catalyst based application.
+
 =head1 METHODS
 
-=over 4
+=cut
 
-=item default
+=head2 default
 
 =cut
 
@@ -555,7 +636,7 @@ sub default : Private {
 #
 # Uncomment and modify this end action after adding a View component
 #
-#=item end
+#=head2 end
 #
 #=cut
 #
@@ -563,11 +644,9 @@ sub default : Private {
 #    my ( $self, $c ) = @_;
 #
 #    # Forward to View unless response body is already defined
-#    $c->forward('View::') unless $c->response->body;
+#    $c->forward( $c->view('') ) unless $c->response->body;
 #}
 
-=back
-
 =head1 AUTHOR
 
 [% author %]
@@ -581,60 +660,39 @@ it under the same terms as Perl itself.
 
 1;
 __makefile__
-    unless ( eval "use Module::Build::Compat 0.02; 1" ) {
-        print "This module requires Module::Build to install itself.\n";
-
-        require ExtUtils::MakeMaker;
-        my $yn =
-          ExtUtils::MakeMaker::prompt( '  Install Module::Build now from CPAN?',            'y' );
-
-        unless ( $yn =~ /^y/i ) {
-            die " *** Cannot install without Module::Build.  Exiting ...\n";
-        }
+use inc::Module::Install;
 
-        require Cwd;
-        require File::Spec;
-        require CPAN;
+name '[% dir %]';
+all_from '[% path %]';
 
-        # Save this 'cause CPAN will chdir all over the place.
-        my $cwd      = Cwd::cwd();
-        my $makefile = File::Spec->rel2abs($0);
+requires Catalyst => '5.64';
 
-        CPAN::Shell->install('Module::Build::Compat')
-          or die " *** Cannot install without Module::Build.  Exiting ...\n";
+catalyst;
 
-        chdir $cwd or die "Cannot chdir() back to $cwd: $!";
-    }
-    eval "use Module::Build::Compat 0.02; 1" or die $@;
-    use lib '_build/lib';
-    Module::Build::Compat->run_build_pl( args => \@ARGV );
-    require Module::Build;
-    Module::Build::Compat->write_makefile( build_class => 'Module::Build' );
-__build__
-use strict;
-use Catalyst::Build;
-
-my $build = Catalyst::Build->new(
-    license            => 'perl',
-    module_name        => '[% name %]',
-    requires           => { Catalyst => '5.49' },
-    create_makefile_pl => 'passthrough',
-    script_files       => [ glob('script/*') ],
-    test_files         => [ glob('t/*.t'), glob('t/*/*.t') ]
-);
-$build->create_build_script;
+install_script glob('script/*.pl');
+auto_install;
+WriteAll;
+__config__
+---
+name: [% name %]
 __readme__
 Run script/[% appprefix %]_server.pl to test the application.
 __changes__
 This file documents the revision history for Perl extension [% name %].
+
 0.01  [% time %]
         - initial revision, generated by Catalyst
 __apptest__
+use strict;
+use warnings;
 use Test::More tests => 2;
-use_ok( Catalyst::Test, '[% name %]' );
 
-ok( request('/')->is_success );
+BEGIN { use_ok 'Catalyst::Test', '[% name %]' }
+
+ok( request('/')->is_success, 'Request should succeed' );
 __podtest__
+use strict;
+use warnings;
 use Test::More;
 
 eval "use Test::Pod 1.14";
@@ -643,6 +701,8 @@ plan skip_all => 'set TEST_POD to enable this test' unless $ENV{TEST_POD};
 
 all_pod_files_ok();
 __podcoveragetest__
+use strict;
+use warnings;
 use Test::More;
 
 eval "use Test::Pod::Coverage 1.04";
@@ -651,7 +711,7 @@ plan skip_all => 'set TEST_POD to enable this test' unless $ENV{TEST_POD};
 
 all_pod_coverage_ok();
 __cgi__
-[% startperl %] -w
+[% startperl %]
 
 BEGIN { $ENV{CATALYST_ENGINE} ||= 'CGI' }
 
@@ -689,7 +749,7 @@ it under the same terms as Perl itself.
 
 =cut
 __fastcgi__
-[% startperl %] -w
+[% startperl %]
 
 BEGIN { $ENV{CATALYST_ENGINE} ||= 'FastCGI' }
 
@@ -701,13 +761,15 @@ use lib "$FindBin::Bin/../lib";
 use [% name %];
 
 my $help = 0;
-my ( $listen, $nproc, $pidfile );
+my ( $listen, $nproc, $pidfile, $manager, $detach );
  
 GetOptions(
     'help|?'      => \$help,
     'listen|l=s'  => \$listen,
     'nproc|n=i'   => \$nproc,
     'pidfile|p=s' => \$pidfile,
+    'manager|M=s' => \$manager,
+    'daemon|d'    => \$detach,
 );
 
 pod2usage(1) if $help;
@@ -716,6 +778,8 @@ pod2usage(1) if $help;
     $listen, 
     {   nproc   => $nproc,
         pidfile => $pidfile, 
+        manager => $manager,
+        detach  => $detach,
     }
 );
 
@@ -740,6 +804,10 @@ pod2usage(1) if $help;
                  requires -listen)
    -p -pidfile   specify filename for pid file
                  (requires -listen)
+   -d -daemon    daemonize (requires -listen)
+   -M -manager   specify alternate process manager
+                 (FCGI::ProcManager sub-class)
+                 or empty string to disable
 
 =head1 DESCRIPTION
 
@@ -758,7 +826,7 @@ it under the same terms as Perl itself.
 
 =cut
 __server__
-[% startperl %] -w
+[% startperl %]
 
 BEGIN { 
     $ENV{CATALYST_ENGINE} ||= 'HTTP';
@@ -776,6 +844,7 @@ my $fork          = 0;
 my $help          = 0;
 my $host          = undef;
 my $port          = 3000;
+my $keepalive     = 0;
 my $restart       = 0;
 my $restart_delay = 1;
 my $restart_regex = '\.yml$|\.yaml$|\.pm$';
@@ -788,6 +857,7 @@ GetOptions(
     'help|?'            => \$help,
     'host=s'            => \$host,
     'port=s'            => \$port,
+    'keepalive|k'       => \$keepalive,
     'restart|r'         => \$restart,
     'restartdelay|rd=s' => \$restart_delay,
     'restartregex|rr=s' => \$restart_regex
@@ -802,12 +872,15 @@ if ( $debug ) {
     $ENV{CATALYST_DEBUG} = 1;
 }
 
+# This is require instead of use so that the above environment
+# variables can be set at runtime.
 require [% name %];
 
 [% name %]->run( $port, $host, {
-    argv   => \@argv,
-    'fork' => $fork,
-    restart => $restart,
+    argv          => \@argv,
+    'fork'        => $fork,
+    keepalive     => $keepalive,
+    restart       => $restart,
     restart_delay => $restart_delay,
     restart_regex => qr/$restart_regex/
 } );
@@ -829,6 +902,7 @@ require [% name %];
    -? -help           display this help and exits
       -host           host (defaults to all)
    -p -port           port (defaults to 3000)
+   -k -keepalive      enable keep-alive connections
    -r -restart        restart when files got modified
                       (defaults to false)
    -rd -restartdelay  delay between file checks
@@ -857,7 +931,7 @@ it under the same terms as Perl itself.
 
 =cut
 __test__
-[% startperl %] -w
+[% startperl %]
 
 use strict;
 use Getopt::Long;
@@ -912,27 +986,26 @@ it under the same terms as Perl itself.
 
 =cut
 __create__
-[% startperl %] -w
+[% startperl %]
 
 use strict;
 use Getopt::Long;
 use Pod::Usage;
 use Catalyst::Helper;
 
-my $help = 0;
-my $nonew = 0;
-my $short = 0;
+my $force = 0;
+my $mech  = 0;
+my $help  = 0;
 
 GetOptions(
-    'help|?' => \$help,
-    'nonew'  => \$nonew,
-    'short'  => \$short
+    'nonew|force'    => \$force,
+    'mech|mechanize' => \$mech,
+    'help|?'         => \$help
  );
 
 pod2usage(1) if ( $help || !$ARGV[0] );
 
-my $helper =
-    Catalyst::Helper->new( { '.newfiles' => !$nonew, short => $short } );
+my $helper = Catalyst::Helper->new( { '.newfiles' => !$force, mech => $mech } );
 
 pod2usage(1) unless $helper->mk_component( '[% name %]', @ARGV );
 
@@ -947,12 +1020,13 @@ pod2usage(1) unless $helper->mk_component( '[% name %]', @ARGV );
 [% appprefix %]_create.pl [options] model|view|controller name [helper] [options]
 
  Options:
-   -help     display this help and exits
-   -nonew    don't create a .new file where a file to be created exists
-   -short    use short types, like C instead of Controller...
+   -force        don't create a .new file where a file to be created exists
+   -mechanize    use Test::WWW::Mechanize::Catalyst for tests if available
+   -help         display this help and exits
 
  Examples:
    [% appprefix %]_create.pl controller My::Controller
+   [% appprefix %]_create.pl -mechanize controller My::Controller
    [% appprefix %]_create.pl view My::View
    [% appprefix %]_create.pl view MyView TT
    [% appprefix %]_create.pl view TT TT
@@ -970,87 +1044,7 @@ Create a new Catalyst Component.
 
 Existing component files are not overwritten.  If any of the component files
 to be created already exist the file will be written with a '.new' suffix.
-This behavior can be suppressed with the C<-nonew> option.
-
-=head1 AUTHOR
-
-Sebastian Riedel, C<sri@oook.de>
-
-=head1 COPYRIGHT
-
-Copyright 2004 Sebastian Riedel. All rights reserved.
-
-This library is free software, you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
-=cut
-__package__
-[% startperl %] -w
-
-use strict;
-use Getopt::Long;
-use Pod::Usage;
-use Catalyst::PAR;
-
-my $core      = 0;
-my $classes   = '';
-my $engine    = 'CGI';
-my $help      = 0;
-my $multiarch = 0;
-my $par       = '[% appprefix %].par';
-
-GetOptions(
-    'classes=s' => \$classes,
-    'core'      => \$core,
-    'engine=s'  => \$engine,
-    'help|?'    => \$help,
-    'multiarch' => \$multiarch,
-    'par=s'     => \$par
-);
-
-pod2usage(1) if $help;
-
-Catalyst::PAR->new->package( {
-    classes   => $classes,
-    core      => $core,
-    engine    => $engine,
-    par       => $par,
-    multiarch => $multiarch,
-    class     => '[% name %]'
-} );
-
-1;
-
-=head1 NAME
-
-[% appprefix %]_package.pl - Package a Catalyst application
-
-=head1 SYNOPSIS
-
-[% appprefix %]_package.pl
-
- Options:
-   -classes      comma separated list of additional classes to
-                 include in package
-   -core         also include modules bundled with Perl (defaults to false)
-   -engine       engine to use for dependency detection (defaults to CGI)
-   -help         display this help and exits
-   -multiarch    enable multiarch support (defaults to false)
-   -par          name for the par archive (defaults to [% appprefix %].par)
-
- Examples:
-   [% appprefix %]_package.pl -engine FastCGI
-   [% appprefix %]_package.pl -par foo_linux_i386_apache2.par -engine Apache2
-   [% appprefix %]_package.pl -classes Test::More,Foo::Bar -par foo.par
-
- See also:
-   perldoc Catalyst::Manual
-   perldoc Catalyst::Manual::Intro
-   perldoc pp
-
-=head1 DESCRIPTION
-
-Package a Catalyst application with L<PAR>.
+This behavior can be suppressed with the C<-force> option.
 
 =head1 AUTHOR
 
@@ -1085,12 +1079,12 @@ Catalyst [% long_type %].
 [% IF long_type == 'Controller' %]
 =head1 METHODS
 
-=over 4
+=cut
 
 #
 # Uncomment and modify this or add new actions to fit your needs
 #
-#=item default
+#=head2 default
 #
 #=cut
 #
@@ -1101,8 +1095,6 @@ Catalyst [% long_type %].
 #    $c->response->body('[% class %] is on Catalyst!');
 #}
 
-=back
-
 [% END %]
 =head1 AUTHOR
 
@@ -1117,15 +1109,28 @@ it under the same terms as Perl itself.
 
 1;
 __comptest__
-[% IF long_type == 'Controller' %]
-use Test::More tests => 3;
-use_ok( Catalyst::Test, '[% app %]' );
-use_ok('[% class %]');
-
-ok( request('[% uri %]')->is_success );
-[% ELSE %]
-use Test::More tests => 1;
-use_ok('[% class %]');
+use strict;
+use warnings;
+[% IF long_type == 'Controller' %][% IF mech %]use Test::More;
+
+eval "use Test::WWW::Mechanize::Catalyst '[% app %]'";
+plan $@
+    ? ( skip_all => 'Test::WWW::Mechanize::Catalyst required' )
+    : ( tests => 2 );
+
+ok( my $mech = Test::WWW::Mechanize::Catalyst->new, 'Created mech object' );
+
+$mech->get_ok( 'http://localhost[% uri %]' );
+[% ELSE %]use Test::More tests => 3;
+
+BEGIN { use_ok 'Catalyst::Test', '[% app %]' }
+BEGIN { use_ok '[% class %]' }
+
+ok( request('[% uri %]')->is_success, 'Request should succeed' );
+[% END %]
+[% ELSE %]use Test::More tests => 1;
+
+BEGIN { use_ok '[% class %]' }
 [% END %]
 __btn_120x50_built__
 89504e470d0a1a0a0000000d4948445200000078000000320803000000a079efea0000000467414d410000d6d8d44f58320000001974455874536f6674776172650041646f626520496d616765526561647971c9653c00000300504c5445d1d3cf8b8a89f4f4f3a4a29dd5d5d3dadad5b38d8bfe0000ef9493dededca1a1a0cb302fdfe0dee4e4e2717170cc8c8cfbfbfbda0101f9f9f975716cc9c3bfc9a6a6cecfcefc3837f945443e3e3ee6e7e6b65756eaeae8d3cccbe9e6e4aeafadcdcecb9d9c99eaa9a8e1e2e0fcf4f3fe1919c9cbc7bc7c7bd7d9d5ffffffcb9393f4f4f4dd5655f1ebe8e4b8b6d9dad8969695e95b5ad3d3d3fbfdfa575757b2b2b2d76665d37575eb7877e2e4e2e40000bbb9b5e2e3e2d5d7d3d58584ecedeba9a9a9d2bab8ccb3b2cac6c5fbfbf9827d78606060f1f1f0c5c5c5e4e5e3bebebbeaece9e43c3cf5d7d7e8e8e6cacac9caafae534c46dedfdcb1b1b0ce7d7cc1c1c07d7e7df1f3eeb9bab8d8d8d7c89d9cf55756e6e8e6f46b6b9a9997676767b4b5b4fd2827cebdbcd8d6d3d5acaabbacab3a322aca5756e3cdcc4e4e4ee0e0e0635d57f20000ec6969aba9a6f47777d2d3d1eeeeeedbdedbcfd0ccdadcd9d0c4c2be6664d94342edcdccadada9434343eddcdc87827dc4c4c2e0ddddf3f3f1e4e6e2dedbdafdfbfae94646dddedbe1e1de92918eeeeeec67625c6a6a6a443d36bcbcbcdededaebd5d4ebeaeadadada7c7874cfcacac49493ececece5d6d5b5b4b1e5c4c3eef1eccd6260b9b7b4908d8ad0d2d0ecc6c5fdfdfb2e261e4f4942d3d2cfbe3a39f2f2f1c2b3b0d81b1bf60a0ad1d1cffe0f0eafb0afccb8b7aeaeadf7f7f7cbccc9dbdcda5a544ec7c8c4737373e6e6e4bbbbbab7b8b6afafad6f6b65acacabb2b5b2ca4e4db3b2afa6a6a3c4c3bf79756fc2c4c1e4e6e4726e67d9dcd8d7d7d6989691e2e0dff5c4c46d67614d47409e9f9d221911dadbd8dadbd9dbdbd9dbdbd8f9f9f7f1f3f1dadad8dcdcdafffffddcdcdbdcdcd9dcdddbfdfffddddddbf7f9f7dadad9fdfdfdf4f7f3f3f1f0eceeecfffdfddbdad8473f39fdfffff9faf9fffdffdcdddadddddaf7f7f9fdfdffbdbbb9f9f7f7b1b2b1f7f4f2e6e5e4ebe3e2e38483e0dcdbdbdad9d36f6ef7e1e0e59898f31818e52b2bf2f4f2d1c9c8d5100fdac6c2dddcdbf7f9f9eceeeed6d1cfe7c8c6b77271ffffff648c2af90000010074524e53ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0053f7072500000a6b4944415478daec586b545357164e68a84d9a041a6b780818a162425a2e0a11814428a258c04041141011ada50a7d400255510a2a216d51caf42d547c4c052d51283a9d8aa52d75941b42b884b7a8287ddaaa9dd63e9c35e3d4d9fb2448e8c3ceac65f935dfbd679fbdbffd9df3dd47c2ca8275e377509ccc7eae4d7ce3b683f53b7d76e173ec80a50bddda26d6b8d64d9871d4c059c4cb58c79e50e3a5556dc90507230f3e93323da86c028d0356b6cd4ff0545edaa28e6e99ee363271c6856d61534e6c894c28a8c8cbdbd8183161c67985bcd59ec37e80c897c2aba707d5ff21c66cb75f626166e4330968ec375c71a9cdedf6a130e0a6319bddd67c741a1c0888d3a6615194f0f514273f2727a7eb6a8f246bc7aa40c1581c23adcc349bd48e1ead49ca6b5e983c6a5cc84b76ff15445e5f0db64e7ed9eeb713caa466e1a8f1ba66c1430497acd3436f93ccf341651af87a12aac4a678ff213b94e0f97ec9d8da4ba3ba9bb8342ec37e6ec4ca9bc61b7d9402a54010a204080410429418f9ad4eabaf6f2104f036d29adbb810a20f51468f8c8c44479373844c5002195d2c1fab49372444c0b137cef6f9554c49f3f9ef30d2d8d81831d23802271ead50165540c20b207511d4ada40bda3d76c66f71f9bf808ecfbfbea4e08435fb79e7e7100945d1c211a108e646187922e1481e5f5e6568141605586b113947405b6b677cf410979b9808c37a127013f9694efd895c6b6ee3a09d489480d2d2512d972b120a8549d6ddf148c491189ed4b65418d0043997b400c072b576c6070635fd9f946afafb7b7bfbe1e8ed2ded85fcc7e0d550699023642fa4c07ffae9a7d02f252da04bfb01b031071dddadc67801a51a0147d8dc267487fc93d13b16818ff89d31e3a4d6aeaeeeeeae6e88873049bd7e3db5fbd08bf34c9003b0d3dddd6d0b5d5621aeb0cd5ddd783b29e1078442031a0bd19cb09ce4ca7acc6f1a7775992476c60a4e4f574f57574f4f4f7e7ecf2309f857c369b5e79c831f428de82107cc30f574c14ca43d563dd2e17093e17c88e1e122928bc27b900d8fadaf80981f4e1a84650c76c6999cf676a3b17db01d10b9c4efe08f050505a97e4b4c581b4ded83a66123f44c46ac4ded0c0c1326d6811a1883ed7fc7d9145f548453bb6970704c6182b570a0416abc9df1b1a67889369723ed3075a4051714f805cf9913ec34e7a0e71463474787c9d861840606134c108c183b6c1c618d3850dcd1515659898b3ada4907ae1bb528b7a9a5f6c67fcd6c69296a69b973eace9953ef9d19b77efdfd083fcfe034ea438a62c8990f9161605014090c959fcf60378cb24af21966906286d993270f5a651f5283d81ac412158b2448d8ddb17a5de6910644d8d4bbaf3dbaf71e826b6fbef9e6d3f7be9ba092a65246c688976b040c33641a05c3649c3c6965300ec3d87cf264bb71bc6a1836a09ecc397c2c770f4bebdb346afc42c6ba23290683afc16068d83b75aad5f79e500c3fddb917698341a2d56a6b59acdc5c8ee1581147da2ad5eedc194fa532cc0b0b72724cf987e07d7cf1c571b837235579f830f4a51c008bc3aaaeadd536371f37487c27d3741bb8f8361c798b18bfc00e2ae3a5946b2562ad569cb6f7d16ba1a1a1f7d846e8b53fdf9d269668c5d8134bc462f14759344de748763e0f137daa4522a609b492c33865bd03a253342dd142ff23b13807a2f63dec2c401a708744ec9b428c7985d39b529a627cf7c05360553ffdf4ccd07198f9d3cc6a6c419395cbaac54d4e3d5fb5a789ceda0d7befce65598df75467d5ecde4dd3350db92c9872595534fd97daea2cba06b3ac53351948a3712d4bd284c68a754776c624c74b542a1547c5e14c39f8eee363087d3cf4dd3d7f8206343918636093187c869c662861ab18150722e49c661895345d456895cab786cee280fc59ecfbaa54f12a15749bd1441b73148c1766fe34551cf962a494621c1d194769fedd8f8fc37a472923858f909191328cb48ca6cba4a0621c8f7f401ef6930c031b3b1a1d1db59bc92d551a9100edb334fd0ac8a71b21c9aa3c0e6bc0f849a994a272930fac64250b1ffd3ee19bfd93f6bfdeabd13cf260da92c7f64f1a87f59f68b6c3a1d16cdf0e71014d6fec86927b07783c0faf7b23773bf86ce16e2faa81fde15a166cd100a1d1708fd034fb593a4b73a81aafb0a66d3b596c829d5468bc9437f3b135c4e1f5fbbfff6e7fdd7771df8f379ea3cbe667eb743e7c1d820d1f165db68fce075e5e830e763acacf7e98a6753afe49787dbaa360cce703c1f7d1659fa71fcea227eb4e64f33f02e6fc0922f7f1e19f186e01e3a094c79cbeb15ac4cd99b7e61f5f97ac196fbce67d81a0047e9a840810f88e0d02c861274108ec77ac44805180511a025b2f1094400ad2920c7cf231b0a695744b04a40b8dd2a224306e7a7dde3ce2109cae4e4f4f77f7f28ab3f78d4b07fa6deca47ba57b79a9e1c6e887cf6f76c77bc02fd62be9ea2a3450c3ae59e7f16ba34e875ebada4bdd810fdf4bed9e030be01ba85627d3d605fc06306e8c7831eee519e03063ed2c7f8f8ad88ad8d8b57576c675f3c22b2e5f7d3bd6c3a3025a15b11e9b613bfabdd8e3e09ab5193e2db11e896044c7f643aca9c2560564a08d8d858b9c1eeb8125f81e821df0bbb8d3a32224fecb95ac034be7c75d593bcb65d6da2bae97f567f57abdd7abfeab466d57f95f9934ebf2d96dae2fbfa6479ccd83d010a6834c1f363f4f4f16e8f51c64f2e687bd96a73f0bc27fe9f528c7cf810e17f0c3a04f94ba308efeb5bcf478057c9ddc92235d66f9bfeaff84cb8ee8ce65c59dd1975de6ee988bcf60d28c2736ed3be35db7eadf3fcc5de5bf69c7039dc5673a9775228aa3e128264534a98bf1245876e60c14cbce14df01cfa4ec874ea0978108a6685842967b18d0b86d61fcfce06ddb5caf3ce03024070cc9372d77f5dee07ff5aaff1b9b8686e4433b5ceaaeeef35ee5eaea3af7b2dc0144430e30c91de45840896108d2af602d56d077805d86e0957c800a54db20ffca011dc22599f827b32c28b3b6d653d52932d79bcda2cf06207abbba2e9ffbd47297b9ce030366d1572b26ada87f60c3860d2bde309bcd030317ebcd174522b3f9e2c5cf6009d4900e98ff691e802ee42248a036e7d4b0516ebe583f801de00688646020af9618df50b82d7da7bc56e51ce51c1818e8ececbccb39306ab1f75d77792f4622102aef3ad7a766d42dff36702b14bb029da3a20277817a6b1476e15047edfb21500d4b5b8188dad7cad90a79a233c2a68872de15056460ab33a4cb6cc6376e2435aecb4db59c3bdd77bacfd2d767396db15864905a2ec820fbfcf469cb62f2ce5dee935d00d6f2f1694bdf39d07ede2723ea3e716ab9422a06e6cb3e99ec63693945b6b140eb82e563325b2c7d172c9673e7be841dfb1c7233c77e08cc4e95dd0a2ee443feb7dfe8ca15e50a85ac5c4129ca79721955aea4784a45b92c20421121067691922753882378f56c4a215e04f2d999633f7d6e6dbc75d52d8d65c498ad58a490511431a694e5608607b072854221c6169401b2ffc958f694ed51ff9631057752ae7849a18890136f4aacb019032be3c903648b2222b07c29e2e7c69c5b1adfb7a2aece75b1ecf660df38e3d9f25babbfbd5db63299fbeccce7468d838a664f2432ca468d2382788a09435240a1f2e67f7de22b174e1ccab27ff79fa87f18fe6f3c61f88f000300c6b973fc89c1298b0000000049454e44ae426082