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

Revision 2609, 31.5 kB (checked in by bchoate, 18 months ago)

Applied patch for GD graphics library support. Thanks, Ogawa-san. BugId:80127

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