root/branches/release-40/lib/MT/App/Wizard.pm @ 2579

Revision 2579, 31.3 kB (checked in by fumiakiy, 18 months ago)

Removing Text::Balanced from extlib; the module depends on another XS module. Added Text::Balanced to mt-check for Perl 5.6.1 users. BugId:80080

Line 
1# Movable Type (r) Open Source (C) 2001-2008 Six Apart, Ltd.
2# This program is distributed under the terms of the
3# GNU General Public License, version 2.
4#
5# $Id$
6
7package MT::App::Wizard;
8
9use strict;
10use base qw( MT::App );
11
12use MT::Util qw( trim );
13
14sub id { 'wizard' }
15
16sub init {
17    my $app = shift;
18    my %param = @_;
19    $app->init_core();
20    my $cfg = $app->config;
21    $cfg->define($app->component('core')->registry('config_settings'));
22    $app->init_core_registry();
23    $cfg->UsePlugins(0);
24    $app->SUPER::init(@_);
25    $app->{mt_dir} ||= $ENV{MT_HOME} || $param{Directory};
26    $app->{is_admin} = 1;
27    $app->add_methods(
28        pre_start => \&pre_start,
29        run_step => \&run_step,
30    );
31    $app->{template_dir} = 'wizard';
32    $app->config->set('StaticWebPath', $app->static_path);
33    return $app;
34}
35
36sub init_request {
37    my $app = shift;
38
39    $app->{default_mode} = 'pre_start';
40
41    # prevents init_request from trying to process the configuration file.
42    $app->SUPER::init_request(@_);
43    $app->set_no_cache;
44    $app->{requires_login} = 0;
45
46    my $mode = $app->mode;
47    return unless $mode eq 'previous_step' || $mode eq 'next_step'
48        || $mode eq 'retry' || $mode eq 'test';
49
50    my $step = $app->param('step') || '';
51
52    my $prev_step = 'pre_start';
53    my $new_step = '';
54
55    if ($mode eq 'retry') {
56        $new_step = $step;
57    } elsif ($mode eq 'test') {
58        $new_step = $step;
59    } else {
60        my $steps = $app->wizard_steps;
61        foreach my $s (@$steps) {
62            if ($mode eq 'next_step') {
63                if ($prev_step eq $step) {
64                    $new_step = $s->{key};
65                    $app->param('save', 1)
66                        if $app->request_method eq 'POST';
67                    last;
68                }
69            } elsif ($mode eq 'previous_step') {
70                if ($s->{key} eq $step) {
71                    $new_step = $prev_step if $prev_step;
72                    last;
73                }
74            }
75            $prev_step = $s->{key};
76        }
77    }
78
79    $app->param('next_step', $new_step);
80    $app->mode('run_step');
81}
82
83sub init_core_registry {
84    my $app = shift;
85    my $core = $app->component("core");
86    $core->{registry}{applications}{wizard} = {
87        wizard_steps => {
88            start => {
89                order => 0,
90                handler => \&start,
91                params => [qw(set_static_uri_to set_static_file_to)],
92            },
93            configure => {
94                order => 100,
95                handler => \&configure,
96                params => [qw(dbpath dbname dbport dbserver dbsocket
97                    dbtype dbuser dbpass publish_charset)]
98            },
99            optional => {
100                order => 200,
101                handler => \&optional,
102                params => [qw(mail_transfer sendmail_path smtp_server
103                    test_mail_address)]
104            },
105            cfg_dir => {
106                order => 300,
107                handler => \&cfg_dir,
108                params => ['temp_dir'],
109                condition => \&cfg_dir_conditions,
110            },
111            seed => {
112                order => 10000,
113                handler => \&seed,
114            },
115        },
116        optional_packages => {
117            'HTML::Entities' => {
118                link => 'http://search.cpan.org/dist/HTML-Entities',
119                label => 'This module is needed to encode special characters, but this feature can be turned off using the NoHTMLEntities option in mt-config.cgi.',
120            },
121            'LWP::UserAgent' => {
122                link => 'http://search.cpan.org/dist/LWP',
123                label => 'This module is needed if you wish to use the TrackBack system, the weblogs.com ping, or the MT Recently Updated ping.',
124            },
125            'SOAP::Lite' => {
126                link => 'http://search.cpan.org/dist/SOAP-Lite',
127                version => 0.50,
128                label => 'This module is needed if you wish to use the MT XML-RPC server implementation.',
129            },
130            'File::Temp' => {
131                link => 'http://search.cpan.org/dist/File-Temp',
132                label => 'This module is needed if you would like to be able to overwrite existing files when you upload.',
133            },
134            'List::Util' => {
135                link => 'http://search.cpan.org/dist/Scalar-List-Utils',
136                label => 'List::Util is optional; It is needed if you want to use the Publish Queue feature.',
137            },
138            'Scalar::Util' => {
139                link => 'http://search.cpan.org/dist/Scalar-List-Utils',
140                label => 'Scalar::Util is optional; It is needed if you want to use the Publish Queue feature.',
141            },
142            'Image::Magick' => {
143                link => 'http://www.imagemagick.org/script/perl-magick.php',
144                label => 'This module is needed if you would like to be able to create thumbnails of uploaded images.',
145            },
146            'Storable' => {
147                link => 'http://search.cpan.org/dist/Storable',
148                label => 'This module is required by certain MT plugins available from third parties.',
149            },
150            'Crypt::DSA' => {
151                link => 'http://search.cpan.org/dist/Crypt-DSA',
152                label => 'This module accelerates comment registration sign-ins.',
153            },
154            'MIME::Base64' => {
155                link => 'http://search.cpan.org/dist/MIME-Base64',
156                label => 'This module is needed to enable comment registration.',
157            },
158            'XML::Atom' => {
159                link => 'http://search.cpan.org/dist/XML-Atom',
160                label => 'This module enables the use of the Atom API.',
161            },
162            'Archive::Tar' => {
163                link => 'http://search.cpan.org/dist/Archive-Tar',
164                label => 'This module is required in order to archive files in backup/restore operation.',
165            },
166            'IO::Compress::Gzip' => {
167                link => 'http://search.cpan.org/dist/IO-Compress-Zlib',
168                label => 'This module is required in order to compress files in backup/restore operation.',
169            },
170            'IO::Uncompress::Gunzip' => {
171                link => 'http://search.cpan.org/dist/IO-Compress-Zlib',
172                label => 'This module is required in order to decompress files in backup/restore operation.',
173            },
174            'Archive::Zip' => {
175                link => 'http://search.cpan.org/dist/Archive-Zip',
176                label => 'This module is required in order to archive files in backup/restore operation.',
177            },
178            'XML::SAX' => {
179                link => 'http://search.cpan.org/dist/XML-SAX',
180                label => 'This module and its dependencies are required in order to restore from a backup.',
181            },
182            'Digest::SHA1' => {
183                link => 'http://search.cpan.org/dist/Digest-SHA1',
184                label => 'This module and its dependencies are required in order to allow commenters to be authenticated by OpenID providers including Vox and LiveJournal.',
185            },
186            'Mail::Sendmail' => {
187                link => 'http://search.cpan.org/dist/Mail-Sendmail',
188                label => 'This module is required for sending mail via SMTP Server.',
189            },
190            'Safe' => {
191                link => 'http://search.cpan.org/dist/Safe',
192                label => 'This module is used in test attribute of MTIf conditional tag.',
193            },
194            'Digest::MD5' => {
195                link => 'http://search.cpan.org/dist/Digest-MD5',
196                label => 'This module is used by the Markdown text filter.',
197            },
198            'Text::Balanced' => {
199                link => 'http://search.cpan.org/dist/Text-Balanced',
200                label => 'This module is required in mt-search.cgi if you are running Movable Type on Perl older than Perl 5.8.',
201            },
202        },
203        required_packages => {
204            'Image::Size' => {
205                link => 'http://search.cpan.org/dist/Image-Size',
206                label => 'This module is required for file uploads (to determine the size of uploaded images in many different formats).',
207            },
208            'CGI::Cookie' => {
209                link => 'http://search.cpan.org/search?query=cgi-cookie&mode=module',
210                label => 'This module is required for cookie authentication.',
211            },
212            'DBI' => {
213                link => 'http://search.cpan.org/dist/DBI',
214                label => 'DBI is required to store data in database.',
215                version => 1.21,
216            },
217            'CGI' => {
218                link => 'http://search.cpan.org/dist/CGI.pm',
219                label => 'CGI is required for all Movable Type application functionality.',
220            },
221            'File::Spec' => {
222                link => 'http://search.cpan.org/dist/File-Spec',
223                version => 0.8,
224                label => 'File::Spec is required for path manipulation across operating systems.',
225            }
226        },
227    };
228}
229
230sub run_step {
231    my $app = shift;
232    my $steps = $app->registry("wizard_steps");
233    my $next_step = $app->param('next_step');
234    my $curr_step = $app->param('step');
235    my $h = $steps->{$curr_step}{handler};
236
237    my %param = $app->unserialize_config;
238    my $keys = $app->config_keys;
239    if ($curr_step) {
240        foreach (@{ $keys->{$curr_step} }) {
241            $param{$_} = $app->param($_)
242                if defined $app->param($_);
243        }
244
245        if ($app->param('save')) {
246            $app->param('config', $app->serialize_config(%param));
247        }
248    }
249
250    $h = $steps->{$next_step}{handler};
251
252    if (!$h) {
253        return $app->pre_start();
254    }
255
256    $h = $app->handler_to_coderef($h)
257        unless ref($h) eq 'CODE';
258
259    $app->param('step', $next_step);
260    return $h->($app, %param);
261}
262
263sub config_keys {
264    my $app = shift;
265    my $steps = $app->registry("wizard_steps");
266    my $keys = {};
267    foreach my $key (keys %$steps) {
268        my $p = $steps->{$key}{params};
269        $keys->{$key} = $p if $p;
270    }
271    return $keys;
272}
273
274sub init_config {
275    return 1;
276}
277
278sub pre_start {
279    my $app = shift;
280    my %param;
281
282    eval { use File::Spec; };
283    my ($cfg, $cfg_exists, $static_file_path);
284    if (!$@) {
285        $cfg = File::Spec->catfile($app->{mt_dir}, 'mt-config.cgi');
286        $cfg_exists |= 1 if -f $cfg;
287
288        $static_file_path = File::Spec->catfile($app->static_file_path);
289    }
290
291    $param{cfg_exists} = $cfg_exists;
292    $param{valid_static_path} = 1 if $app->is_valid_static_path($app->static_path);
293    $param{mt_static_exists} = $app->mt_static_exists;
294    $param{static_file_path} = $static_file_path;
295
296    return $app->build_page("start.tmpl", \%param);
297}
298
299sub wizard_steps {
300    my $app = shift;
301    my @steps;
302    my $steps = $app->registry("wizard_steps");
303    my $active_step = $app->param('step') || 'start';
304    my %param = $app->unserialize_config;
305    foreach my $key (keys %$steps) {
306        if (my $cond = $steps->{$key}{condition}) {
307            if (!ref($cond)) {
308                $cond = $app->handler_to_coderef($cond);
309            }
310            next unless ref($cond) eq 'CODE';
311            next unless $cond->($app, \%param);
312        }
313        push @steps, {
314            key => $key,
315            active => $active_step eq $key,
316            %{$steps->{$key}},
317        };
318    }
319    @steps = sort { $a->{order} <=> $b->{order} } @steps;
320    return \@steps;
321}
322
323sub build_page {
324    my $app = shift;
325    my ($tmpl, $param) = @_;
326
327    $param ||= {};
328    my $steps = $app->wizard_steps;
329    $param->{'wizard_steps'} = $steps;
330    $param->{'step'} = $app->param('step');
331
332    return $app->SUPER::build_page($tmpl, $param);
333}
334
335sub start {
336    my $app = shift;
337    my %param = @_;
338
339    my $static_path = $app->param('set_static_uri_to');
340    my $static_file_path = defined $param{set_static_file_to} ?
341        $param{set_static_file_to} :
342        $app->param('set_static_file_to');
343    $param{set_static_file_to} = $static_file_path;
344
345    # test for static_path
346    unless ($app->param('set_static_uri_to')) {
347        $param{uri_invalid} = 1;
348        return $app->build_page("start.tmpl", \%param);
349    }
350
351    $static_path = $app->cgipath . $static_path
352        unless $static_path =~ m#^(https?:/)?/#;
353    $static_path =~ s#(^\s+|\s+$)##;
354    $static_path .= '/' unless $static_path =~ m!/$!;
355
356    unless ($app->is_valid_static_path($static_path)) {
357        $param{uri_invalid} = 1;
358        $param{set_static_uri_to} = $app->param('set_static_uri_to');
359        return $app->build_page("start.tmpl", \%param);
360    }
361
362    $app->config->set('StaticWebPath', $static_path);
363
364    # test for static_file_path
365    unless ($static_file_path) {
366        $param{file_invalid} = 1;
367        return $app->build_page("start.tmpl", \%param);
368    }
369   
370    if (!(-d $static_file_path) || !(-f File::Spec->catfile($static_file_path, "mt.js"))) {
371        $param{file_invalid} = 1;
372        $param{set_static_uri_to} = $app->param('set_static_uri_to');
373        return $app->build_page("start.tmpl", \%param);
374    }
375    $param{config} = $app->serialize_config(%param);
376    $param{static_file} = $static_file_path;
377
378    # test for required packages...
379    my $req = $app->registry("required_packages");
380    my @REQ;
381    foreach my $key (keys %$req) {
382        my $pkg = $req->{$key};
383        push @REQ, [ $key, $pkg->{version} || 0, 1, $pkg->{label}, $key, $pkg->{link} ];
384    }
385    my ($needed) = $app->module_check(\@REQ);
386    if (@$needed) {
387        $param{package_loop} = $needed;
388        $param{required} = 1;
389        return $app->build_page("packages.tmpl", \%param);
390    }
391
392    my @DATA;
393    my $drivers = $app->object_drivers;
394    foreach my $key (keys %$drivers) {
395        my $driver = $drivers->{$key};
396        my $label = $driver->{label};
397        my $link = 'http://search.cpan.org/dist/' . $driver->{dbd_package};
398        $link =~ s/::/-/g;
399        push @DATA, [ $driver->{dbd_package}, $driver->{dbd_version}, 0,
400            $app->translate("The [_1] database driver is required to use [_2].", $driver->{dbd_package}, $label),
401            $label, $link ];
402    }
403    my ($db_missing) = $app->module_check(\@DATA);
404    if ((scalar @$db_missing) == (scalar @DATA)) {
405        $param{package_loop} = $db_missing;
406        $param{missing_db_or_optional} = 1;
407        $param{missing_db} = 1;
408        return $app->build_page("packages.tmpl", \%param);
409    }
410
411    my $opt = $app->registry("optional_packages");
412    my @OPT;
413    foreach my $key (keys %$opt) {
414        my $pkg = $opt->{$key};
415        push @OPT, [ $key, $pkg->{version} || 0, 0, $pkg->{label}, $key, $pkg->{link} ];
416    }
417    my ($opt_missing) = $app->module_check(\@OPT);
418    push @$opt_missing, @$db_missing;
419    if (@$opt_missing) {
420        $param{package_loop} = $opt_missing;
421        $param{missing_db_or_optional} = 1;
422        $param{optional} = 1;
423        return $app->build_page("packages.tmpl", \%param);
424    }
425
426    $param{success} = 1;
427    return $app->build_page("packages.tmpl", \%param);
428}
429
430sub object_drivers {
431    my $app = shift;
432    my $drivers = $app->registry("object_drivers") || {};
433    return $drivers;
434}
435
436sub configure {
437    my $app = shift;
438    my %param = @_;
439
440    $param{set_static_uri_to} = $app->param('set_static_uri_to');
441    # set static web path
442    $app->config->set('StaticWebPath', $param{set_static_uri_to});
443    delete $param{publish_charset};
444    if (my $dbtype = $param{dbtype}) {
445        $param{"dbtype_$dbtype"} = 1;
446        if ($dbtype eq 'mysql') {
447            $param{login_required} = 1;
448        } elsif ($dbtype eq 'postgres') {
449            $param{login_required} = 1;
450        } elsif ($dbtype eq 'oracle') {
451            $param{login_required} = 1;
452        } elsif ($dbtype eq 'mssqlserver') {
453            $param{login_required} = 1;
454            $param{publish_charset} = $app->param('publish_charset') || ($app->{cfg}->DefaultLanguage eq 'ja' ? 'Shift_JIS' : 'ISO-8859-1');
455        } elsif ($dbtype eq 'sqlite') {
456            $param{path_required} = 1;
457        } elsif ($dbtype eq 'sqlite2') {
458            $param{path_required} = 1;
459        }
460    }
461
462    my @DATA;
463    my $drivers = $app->object_drivers;
464    foreach my $key (keys %$drivers) {
465        my $driver = $drivers->{$key};
466        my $label = $driver->{label};
467        my $link = 'http://search.cpan.org/dist/' . $driver->{dbd_package};
468        $link =~ s/::/-/g;
469        push @DATA, [ $driver->{dbd_package}, $driver->{dbd_version}, 0,
470            $app->translate("The [_1] driver is required to use [_2].", $driver->{dbd_package}, $label),
471            $label, $link ];
472    }
473    my ($missing, $dbmod) = $app->module_check(\@DATA);
474    if (scalar(@$dbmod) == 0) {
475        $param{missing_db_or_optional} = 1;
476        $param{missing_db} = 1;
477        $param{package_loop} = $missing;
478        return $app->build_page("packages.tmpl", \%param);
479    }
480    foreach (@$dbmod) {
481        if ($_->{module} eq 'DBD::mysql') {
482            $_->{id} = 'mysql';
483        } elsif ($_->{module} eq 'DBD::Pg') {
484            $_->{id} = 'postgres';
485        } elsif ($_->{module} eq 'DBD::Oracle') {
486            $_->{id} = 'oracle';
487        } elsif ($_->{module} eq 'DBD::ODBC1.13') {
488            $_->{id} = 'mssqlserver';
489        } elsif ($_->{module} eq 'DBD::ODBC1.14') {
490            $_->{id} = 'umssqlserver';
491        } elsif ($_->{module} eq 'DBD::SQLite') {
492            $_->{id} = 'sqlite';
493        } elsif ($_->{module} eq 'DBD::SQLite2') {
494            $_->{id} = 'sqlite2';
495        }
496        if ($param{dbtype} && ($param{dbtype} eq $_->{id})) {
497            $_->{selected} = 1;
498        }
499    }
500    $param{db_loop} = $dbmod;
501    $param{one_db} = $#$dbmod == 0; # db module is only one or not
502    $param{config} = $app->serialize_config(%param);
503
504    my $ok = 1;
505    my ($err_msg, $err_more);
506    if ($app->param('test')) {
507        # if check successfully and push continue then goto next step
508        $ok = 0;
509        my $dbtype = $param{dbtype};
510        my $driver = $drivers->{$dbtype}{config_package}
511            if exists $drivers->{$dbtype};
512        $param{dbserver_null} = 1 unless $param{dbserver};
513
514        if ($driver) {
515            my $cfg = $app->config;
516            $cfg->ObjectDriver($driver);
517            $cfg->Database($param{dbname}) if $param{dbname};
518            $cfg->DBUser($param{dbuser}) if $param{dbuser};
519            $cfg->DBPassword($param{dbpass}) if $param{dbpass};
520            $cfg->DBPort($param{dbport}) if $param{dbport};
521            $cfg->DBSocket($param{dbsocket}) if $param{dbsocket};
522            $cfg->DBHost($param{dbserver}) 
523              if $param{dbserver} && ( $param{dbtype} ne 'oracle' );
524            $cfg->PublishCharset($param{publish_charset})
525                if $param{publish_charset};
526            if ($dbtype eq 'sqlite' || $dbtype eq 'sqlite2') {
527                require File::Spec;
528                my $db_file = $param{dbpath};
529                if (!File::Spec->file_name_is_absolute($db_file)) {
530                    $db_file = File::Spec->catfile($app->{mt_dir}, $db_file);
531                }
532                $cfg->Database($db_file) if  $db_file;
533                $param{dbpath} = $db_file if  $db_file;
534                if ($dbtype eq 'sqlite2') {
535                    $cfg->UseSQLite2(1);
536                }
537            }
538            # test loading of object driver with these parameters...
539            require MT::ObjectDriverFactory;
540            my $od = MT::ObjectDriverFactory->new($driver);
541            eval { $od->rw_handle; }; ## to test connection
542            if (my $err = $@) {
543                $err_msg = $app->translate('An error occurred while attempting to connect to the database.  Check the settings and try again.');
544                $err_more = $err;
545            } else {
546                $ok = 1;
547            }
548        }
549        if ($ok) {
550            $param{success} = 1;
551            return $app->build_page("configure.tmpl", \%param);
552        }
553        $param{connect_error} = 1;
554        $param{error} = $err_msg;
555        $param{error_more} = $err_more;
556    }
557
558    $app->build_page("configure.tmpl", \%param);
559}
560
561my @Sendmail = qw( /usr/lib/sendmail /usr/sbin/sendmail /usr/ucblib/sendmail );
562
563sub cfg_dir_conditions {
564    my $app = shift;
565    my ($param) = @_;
566    if ($^O ne 'MSWin32') {
567        # check for writable temp directory
568        if (-w "/tmp") {
569            return 0;
570        }
571    }
572    return 1;
573}
574
575sub cfg_dir {
576    my $app = shift;
577    my %param = @_;
578
579    $param{set_static_uri_to} = $app->param('set_static_uri_to');
580
581    # set static web path
582    $app->config->set('StaticWebPath', $param{set_static_uri_to});
583
584    $param{config} = $app->serialize_config(%param);
585
586    my $temp_dir;
587    if ($app->param('test')) {
588        $param{changed} = 1;
589        if ($param{temp_dir}) {
590            $temp_dir = $param{temp_dir};
591        } else {
592            $param{invalid_error} = 1;
593        }
594    } else {
595        if ($param{temp_dir}) {
596            $temp_dir = $param{temp_dir};
597            $param{changed} = 1;
598        } else {
599            $temp_dir = $app->config->TempDir;
600            if (!-d $temp_dir) {
601                if ($^O eq 'MSWin32') {
602                    $temp_dir = 'C:\Windows\Temp';
603                }
604            }
605            $param{temp_dir} = $temp_dir;
606        }
607    }
608
609    # check temp dir
610    if ($temp_dir) {
611        if (!-d $temp_dir) {
612            $param{not_found_error} = 1;
613        } elsif (!-w $temp_dir) {
614            $param{not_write_error} = 1;
615        } else {
616            $param{success} = 1;
617        }
618    }
619
620    $app->build_page("cfg_dir.tmpl", \%param);
621}
622
623sub optional {
624    my $app = shift;
625    my %param = @_;
626
627    $param{set_static_uri_to} = $app->param('set_static_uri_to');
628
629    # set static web path
630    $app->config->set('StaticWebPath', $param{set_static_uri_to});
631
632    # discover sendmail
633    my $mgr = $app->config;
634    my $sm_loc;
635    for my $loc ($param{sendmail_path}, @Sendmail) {
636        next unless $loc;
637        $sm_loc = $loc, last if -x $loc && !-d $loc;
638    }
639    $param{sendmail_path} = $sm_loc || '';
640
641    my $transfer;
642    push @$transfer, {id => 'smtp', name => $app->translate('SMTP Server')};
643    push @$transfer, {id => 'sendmail', name => $app->translate('Sendmail')};
644
645    foreach(@$transfer){
646        if ($_->{id} eq $param{mail_transfer}) {
647            $_->{selected} = 1;
648        }
649    }
650
651    $param{'use_'.$param{mail_transfer}} = 1;
652    $param{mail_loop} = $transfer;
653    $param{config} = $app->serialize_config(%param);
654
655    my $ok = 1;
656    my $err_msg;
657    if ($app->param('test')) {
658        $ok = 0;
659        if ($param{test_mail_address}){
660            my $cfg = $app->config;
661            $cfg->MailTransfer($param{mail_transfer}) if $param{mail_transfer};
662            $cfg->SMTPServer($param{smtp_server}) if $param{mail_transfer} && ($param{mail_transfer} eq 'smtp') && $param{smtp_server};
663            $cfg->SendMailPath($param{sendmail_path}) if $param{mail_transfer} && ($param{mail_transfer} eq 'sendmail') && $param{sendmail_path};
664            my %head = (id => 'wizard_test',
665                        To => $param{test_mail_address},
666                        From => $cfg->EmailAddressMain || $param{test_mail_address},
667                        Subject => $app->translate("Test email from Movable Type Configuration Wizard") );
668            my $charset = $cfg->MailEncoding || $cfg->PublishCharset;
669            $head{'Content-Type'} = qq(text/plain; charset="$charset");
670
671            my $body = $app->translate("This is the test email sent by your new installation of Movable Type.");
672
673            require MT::Mail;
674            $ok = MT::Mail->send(\%head, $body);
675
676            if ($ok){
677                $param{success} = 1;
678                return $app->build_page("optional.tmpl", \%param);
679            }else{
680                $err_msg = MT::Mail->errstr;
681            }
682        }
683       
684        $param{send_error} = 1;
685        $param{error} = $err_msg;
686    }
687    $app->build_page("optional.tmpl", \%param);
688}
689
690sub seed {
691    my $app = shift;
692    my %param = @_;
693
694    # input data unserialize to config
695    unless (keys(%param)) {
696        $param{config} = $app->param('config');
697    }else{
698        $param{config} = $app->serialize_config(%param);
699    }
700
701    $param{static_file_path} = $param{set_static_file_to};
702
703    require URI;
704    my $uri = URI->new($app->cgipath);
705    $param{cgi_path} = $uri->path;
706    $uri = URI->new($app->param->param('set_static_uri_to'));
707    $param{static_web_path} = $uri->path;
708    $param{static_uri} = $uri->path;
709    my $drivers = $app->object_drivers;
710
711    my $r_uri = $ENV{REQUEST_URI} || $ENV{SCRIPT_NAME};
712    if ($ENV{MOD_PERL} || (($r_uri =~ m/\/mt-wizard\.(\w+)(\?.*)?$/) && ($1 ne 'cgi'))) {
713        my $new = '';
714        if ($ENV{MOD_PERL}) {
715            $param{mod_perl} = 1;
716        } else {
717            $new = '.' . $1;
718        }
719        my @scripts;
720        my $cfg = $app->config;
721        my @cfg_keys = grep { /Script$/ } keys %{ $cfg->{__settings} };
722        $param{mt_script} = $app->config->AdminScript;
723        foreach my $key (@cfg_keys) {
724            my $path = $cfg->get($key);
725            $path =~ s/\.cgi$/$new/;
726            if (-e File::Spec->catfile($app->{mt_dir}, $path)) {
727                $param{mt_script} = $path if $key eq 'AdminScript';
728                push @scripts, { name => $key, path => $path };
729            }
730        }
731        if (@scripts) {
732            $param{script_loop} = \@scripts if @scripts;
733            $param{non_cgi_suffix} = 1;
734        }
735    } else {
736        $param{mt_script} = $app->config->AdminScript;
737    }
738
739    # unserialize database configuration
740    if (my $dbtype = $param{dbtype}) {
741        if ($dbtype eq 'sqlite') {
742            $param{use_dbms} = 1;
743            $param{object_driver} = 'DBI::sqlite';
744            $param{database_name} = $param{dbpath};
745        } elsif ($dbtype eq 'sqlite2') {
746            $param{use_dbms} = 1;
747            $param{use_sqlite2} = 1;
748            $param{object_driver} = 'DBI::sqlite';
749            $param{database_name} = $param{dbpath};
750        } else {
751            $param{use_dbms} = 1;
752            $param{object_driver} = $drivers->{$dbtype}{config_package};
753            $param{database_name} = $param{dbname};
754            $param{database_username} = $param{dbuser};
755            $param{database_password} = $param{dbpass} if $param{dbpass};
756            $param{database_host} = $param{dbserver}
757                if ($dbtype ne 'oracle') && $param{dbserver};
758            $param{database_port} = $param{dbport} if $param{dbport};
759            $param{database_socket} = $param{dbsocket} if $param{dbsocket};
760            $param{use_setnames} =  $param{setnames} if $param{setnames};
761            $param{publish_charset} =  $param{publish_charset}
762                if $param{publish_charset};
763        }
764    }
765
766    if ($param{temp_dir} eq $app->config->TempDir) {
767        $param{temp_dir} = '';
768    }
769
770    # authentication configuration
771    $param{help_url} = $app->help_url();
772
773    my $tmpls = $app->registry("wizard_template") || [];
774
775    my @tmpl_loop;
776    require MT::Template;
777    foreach my $code (@$tmpls) {
778        if ($code = $app->handler_to_coderef($code)) {
779            push @tmpl_loop, { tmpl_code => $code };
780        }
781    }
782
783    $param{tmpl_loop} = \@tmpl_loop;
784
785    my $data = $app->build_page("mt-config.tmpl", \%param);
786
787    my $cfg_file = File::Spec->catfile($app->{mt_dir}, 'mt-config.cgi');
788    if (!-f $cfg_file) {
789        # write!
790        if (open OUT, ">$cfg_file") {
791            print OUT $data;
792            close OUT;
793        }
794        $param{config_created} = 1 if -f $cfg_file;
795        $param{config_file} = $cfg_file;
796        if ((!-f $cfg_file) && $app->param->param('manually')) {
797            $param{file_not_found} = 1;
798            $param{manually} = 1;
799        }
800    } elsif($app->param->param('manually')) {
801        $param{config_created} = 1 if -f $cfg_file;
802        $param{config_file} = $cfg_file;
803    }
804
805    # back to the complete screen
806    return $app->build_page("complete.tmpl", \%param);
807}
808
809sub serialize_config {
810    my $app = shift;
811    my %param = @_;
812 
813    require MT::Serialize;
814    my $ser = MT::Serialize->new('MT');
815    my $keys = $app->config_keys();
816    my %set;
817    foreach my $key (keys %$keys) {
818        foreach my $p (@{$keys->{$key}}) {
819            $set{$p} = $param{$p};
820        }
821    }
822    my $set = \%set;
823    unpack 'H*', $ser->serialize(\$set);
824}
825
826sub unserialize_config {
827    my $app = shift;
828    my $data = $app->param('config');
829    my %config;
830    if ($data) {
831        $data = pack 'H*', $data;
832        require MT::Serialize;
833        my $ser = MT::Serialize->new('MT');
834        my $thawed = $ser->unserialize($data);
835        if ($thawed) {
836            my $saved_cfg = $$thawed;
837            if (keys %$saved_cfg) {
838                foreach my $p (keys %$saved_cfg) {
839                    $config{$p} = $saved_cfg->{$p};
840                }
841            }
842        }
843    }
844    %config;
845}
846
847sub cgipath {
848    my $app = shift;
849
850    # these work for Apache... need to test for IIS...
851    my $host = $ENV{SERVER_NAME} || $ENV{HTTP_HOST};
852    $host =~ s/:\d+//; # eliminate any port that may be present
853    my $port = $ENV{SERVER_PORT};
854    # REQUEST_URI for CGI-compliant servers; SCRIPT_NAME for IIS.
855    my $uri = $ENV{REQUEST_URI} || $ENV{SCRIPT_NAME};
856    $uri =~ s!/mt-wizard(\.f?cgi|\.f?pl)(\?.*)?$!/!;
857
858    my $cgipath = '';
859    $cgipath = $port == 443 ? 'https' : 'http';
860    $cgipath .= '://' . $host;
861    $cgipath .= ($port == 443 || $port == 80) ? '' : ':' . $port;
862    $cgipath .= $uri;
863
864    $cgipath;
865}
866
867sub module_check {
868    my $self = shift;
869    my $modules = shift;
870    my (@missing, @ok);
871    foreach my $ref (@$modules) {
872        my($mod, $ver, $req, $desc, $name, $link) = @$ref;
873        eval("use $mod" . ($ver ? " $ver;" : ";"));
874        $mod .= $ver if $mod eq 'DBD::ODBC';
875        if ($@) {
876            push @missing, { module => $mod,
877                             version => $ver,
878                             required => $req,
879                             description => $desc,
880                             label => $name,
881                             link => $link };
882        } else {
883            push @ok, { module => $mod,
884                        version => $ver,
885                        required => $req,
886                        description => $desc,
887                        label => $name,
888                        link => $link };
889        }
890    }
891    (\@missing, \@ok);
892}
893
894sub static_path {
895    my $app = shift;
896    my $static_path = '';
897
898    if ($app->config->StaticWebPath ne '') {
899        $static_path = $app->config->StaticWebPath;
900        $static_path .= '/' unless $static_path =~ m!/$!;
901        return $static_path;
902    }
903    return $app->mt_static_exists ? $app->cgipath.'mt-static/' : '';
904}
905
906sub mt_static_exists {
907    my $app = shift;
908    return (-f File::Spec->catfile($app->{mt_dir}, "mt-static", "mt.js")) ? 1 : 0;
909}
910
911sub is_valid_static_path {
912    my $app = shift;
913    my ($static_uri) = @_;
914
915    my $path;
916    if ($static_uri =~ m/^http/i) {
917        $path = $static_uri . 'mt.js';
918    } elsif($static_uri =~ m#^/#) {
919        my $host = $ENV{SERVER_NAME} || $ENV{HTTP_HOST};
920        $host =~ s/:\d+//; # eliminate any port that may be present
921        my $port = $ENV{SERVER_PORT};
922        $path = $port == 443 ? 'https' : 'http';
923        $path .= '://' . $host;
924        $path .= ($port == 443 || $port == 80) ? '' : ':' . $port;
925        $path .= $static_uri . 'mt.js';
926    }
927    else {
928        $path = $app->cgipath . $static_uri . 'mt.js';
929    }
930
931    require LWP::UserAgent;
932    my $ua = LWP::UserAgent->new;
933    my $request = HTTP::Request->new(GET => $path);
934    my $response = $ua->request($request);
935    $response->is_success and ($response->content_length() != 0) && ($response->content =~ m/function\s+openManual/s);
936}
9371;
938__END__
939
940=head1 NAME
941
942MT::App::Wizard
943
944=head1 METHODS
945
946TODO
947
948=head1 AUTHOR & COPYRIGHT
949
950Please see L<MT/AUTHOR & COPYRIGHT>.
951
952=cut
Note: See TracBrowser for help on using the browser.