/[Perly]/lib/Perly/Action/Run.pm
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /lib/Perly/Action/Run.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 38 - (show annotations)
Sat Jun 9 22:53:52 2007 UTC (16 years, 11 months ago) by dpavlin
File size: 3035 byte(s)
spit out directory and command before exec
1 use strict;
2 use warnings;
3
4 =head1 NAME
5
6 Perly::Action::Run
7
8 =cut
9
10 package Perly::Action::Run;
11 use base qw/Perly::Action Jifty::Action/;
12
13 use Data::Dump qw/dump/;
14 use File::Temp qw/tempdir/;
15 use File::Slurp;
16 use Cwd qw/cwd/;
17 use Perly::Depends;
18
19 use Jifty::Param::Schema;
20 use Jifty::Action schema {
21
22 param input =>
23 label is 'Input data',
24 available are defer {
25 my $coll = Perly::Model::InputCollection->new;
26 $coll->unlimit;
27 [ '', {
28 display_from => 'name',
29 value_from => 'id',
30 collection => $coll,
31 }];
32 },
33 render as 'Select';
34
35 param code =>
36 label is 'Source code',
37 available are defer {
38 my $coll = Perly::Model::CodeCollection->new;
39 $coll->unlimit;
40 [{
41 display_from => 'name',
42 value_from => 'id',
43 collection => $coll,
44 }];
45 },
46 render as 'Select',
47 is mandatory;
48 };
49
50 sub sticky_on_success { 1 }
51 sub sticky_on_failure { 1 }
52
53 =head2 take_action
54
55 This action is B<huge security hole>. It executes script entered over web
56 page, without any sandboxing in new shell under user running Jifty.
57
58 =cut
59
60 sub take_action {
61 my $self = shift;
62
63 my $code = Perly::Model::Code->new;
64 $code->load( $self->argument_value( 'code' ) ) or die "can't load code";
65
66 my $input = Perly::Model::Input->new;
67 if ( my $input_id = $self->argument_value( 'input' ) ) {
68 $input->load( $input_id ) or die "can't load $input_id";
69 }
70
71 my $cwd = cwd;
72 my $dir = tempdir( '/tmp/perly-XXXX', CLEANUP => 1 );
73
74 chdir( $dir ) || die "can't chdir $dir";
75
76 write_file( $code->name, $code->source ) or die "can't write " . $code->name . ": $!";
77 chmod 0700, $code->name;
78 my $cmd = './' . $code->name;
79 my $message = '$ <a href="/edit?id=' . $code->id . '">' . $code->name . '</a>';
80
81 my $deps = Perly::Depends->parse( $code->source );
82 foreach my $module ( @{ $deps->{depends_on} } ) {
83 my $filename = $module . '.pm';
84 my $dep_code = Perly::Model::Code->new;
85 $dep_code->load_by_cols( name => $filename );
86 die "can't find $filename -- do you need to create it first?\n" unless ( $dep_code->id );
87 write_file( $filename, $dep_code->source ) or die "can't write $filename: $!";
88 warn "dependency $module in file $filename\n";
89 }
90
91 if ( $input->content ) {
92 write_file( $input->name, $input->content ) or die "can't write " . $input->name . ": $!";
93 $cmd .= ' ' . $input->name;
94 $message .= ' ' . $input->name;
95 $self->result->content( input => $input->content );
96 }
97
98 my $output;
99 my $timeout = Jifty->config->app('timeout') || 10;
100
101 eval {
102 local $SIG{ALRM} = sub { die "Aborted execution after $timeout sec.\n" }; # NB: \n required
103 alarm $timeout;
104 warn ">> $dir >> $cmd\n";
105 $output = `$cmd 2>&1`;
106 alarm 0;
107 };
108 if ($@) {
109 die "$@\n" unless $@ eq "alarm\n"; # propagate unexpected errors
110 }
111
112 $output =~ s/^Can't ignore signal CHLD, forcing to default\.\n//s;
113 $self->result->content( output => $output );
114
115 warn "$message\n$output\n";
116
117 chdir( $cwd ) || die "can't return to $cwd";
118
119 $self->result->message( $message );
120
121 #warn "content in action = ",dump( $self->result->content );
122
123 return 1;
124 }
125
126 1;
127

  ViewVC Help
Powered by ViewVC 1.1.26