13 # You should have received a copy of the GNU General Public License |
13 # You should have received a copy of the GNU General Public License |
14 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
14 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
15 |
15 |
16 use Mojolicious::Lite; |
16 use Mojolicious::Lite; |
17 use UUID; |
17 use UUID; |
18 use Mojo::JSON; |
|
19 use Mojo::ByteStream 'b'; |
|
20 use Mojo::UserAgent; |
|
21 use lib 'lib'; |
18 use lib 'lib'; |
22 |
19 |
23 my @valid_params = qw/Add-ons Distributor ProductName ReleaseChannel StartupTime UserID Version BuildID CrashTime Comments/; |
20 use CrashTest::Models::Frame; |
24 my $config = plugin 'Config'; |
21 use CrashTest::Models::Thread; |
25 |
22 use CrashTest::StackFilter; |
26 plugin 'TagHelpers::BootstrapPagination'; |
|
27 |
23 |
28 app->attr(storage => sub { |
24 app->attr(storage => sub { |
29 my $self = shift; |
25 my $self = shift; |
30 my $loader = Mojo::Loader->new; |
26 my $loader = Mojo::Loader->new; |
31 |
27 |
51 dumper_config => $self->app->config->{Dumper}, |
47 dumper_config => $self->app->config->{Dumper}, |
52 storage => $self->app->storage |
48 storage => $self->app->storage |
53 ); |
49 ); |
54 }); |
50 }); |
55 |
51 |
56 helper scm_file_link => sub { |
|
57 my ($self, $file, $line) = @_; |
|
58 |
|
59 return "" unless(defined($file)); |
|
60 |
|
61 if($file =~ qr{([a-z]+):([a-z/.]+):(.+):(\d+)}) |
|
62 { |
|
63 my ($scm, $repo, $scmpath, $rev) = ($1, $2, $3, $4); |
|
64 my $filename = File::Spec->splitpath($scmpath); |
|
65 my $scmrepo = "$scm:$repo"; |
|
66 if(exists($config->{ScmLinks}->{$scmrepo})) { |
|
67 return b($self->link_to("$filename:$line" => |
|
68 $self->render(inline => $config->{ScmLinks}->{$scmrepo}, |
|
69 repo => $repo, scmpath => $scmpath, rev => $rev, line => $line, partial => 1) |
|
70 )); |
|
71 } |
|
72 #return $file; |
|
73 } |
|
74 my $filebase = (File::Spec->splitpath($file))[-1]; |
|
75 if(defined($line) && $line ne "") { |
|
76 return "$filebase:$line"; |
|
77 } |
|
78 return $filebase; |
|
79 }; |
|
80 |
|
81 helper shorten_signature => sub { |
|
82 my ($self, $signature) = @_; |
|
83 |
|
84 return "" if(!defined($signature) || $signature eq ""); |
|
85 |
|
86 my $short_signature = $signature; |
|
87 if($signature =~ qr{([^<]+)<.+>::([^()]+)\(.*\)(.*)}) { |
|
88 # c++ with template |
|
89 $short_signature = "$1<>::$2()$3"; |
|
90 } elsif($signature =~ qr{([^()]+)\(.*\)(.*)}) { |
|
91 # c/c++ |
|
92 $short_signature = "$1()$2"; |
|
93 } |
|
94 return b($self->t(span => (title => $signature, class => "shortened-signature") => $short_signature)); |
|
95 }; |
|
96 |
|
97 helper xml_escape_block => sub { |
|
98 my ($c, $block) = @_; |
|
99 my $result = $block->(); |
|
100 $result = xml_escape $result; |
|
101 return Mojo::ByteStream->new($result); |
|
102 }; |
|
103 |
|
104 get '/' => sub { |
52 get '/' => sub { |
105 my $self = shift; |
53 my $self = shift; |
106 my $page = 1; |
54 my $page = 1; |
107 $self->validation->required('page')->like(qr/^[0-9]+$/); |
55 $self->validation->required('page')->like(qr/^[0-9]+$/); |
108 $page = scalar $self->validation->param("page") if $self->validation->is_valid('page'); |
56 $page = scalar $self->validation->param("page") if $self->validation->is_valid('page'); |
114 $self->render('index'); |
62 $self->render('index'); |
115 } => 'index'; |
63 } => 'index'; |
116 |
64 |
117 get '/report/:uuid' => [ uuid => qr/[0-9a-fA-F-]+/ ] => sub { |
65 get '/report/:uuid' => [ uuid => qr/[0-9a-fA-F-]+/ ] => sub { |
118 my $self = shift; |
66 my $self = shift; |
119 $self->stash(processed_data => $self->app->storage->get_processed_data($self->param('uuid'))); |
67 |
|
68 my $data = $self->app->storage->get_processed_data($self->param('uuid')); |
|
69 $self->stash(processed_data => $data); |
|
70 |
|
71 my $stackfilter = CrashTest::StackFilter->new(config => $self->app->config, app => $self->app); |
|
72 |
|
73 my $crashing_thread = CrashTest::Models::Thread->new($data->{crashing_thread}); |
|
74 $crashing_thread = $stackfilter->apply($crashing_thread); |
|
75 $self->stash(crashing_thread => $crashing_thread); |
|
76 |
|
77 my $threads = []; |
|
78 foreach my $raw_thread(@{$data->{threads}}) { |
|
79 my $thread = CrashTest::Models::Thread->new($raw_thread); |
|
80 $thread = $stackfilter->apply($thread); |
|
81 push $threads, $thread; |
|
82 } |
|
83 $self->stash(threads => $threads); |
|
84 |
120 $self->render('report/crash'); |
85 $self->render('report/crash'); |
121 } => 'report'; |
86 } => 'report'; |
122 |
87 |
123 post '/submit' => sub { |
88 post '/submit' => sub { |
124 my $self = shift; |
89 my $self = shift; |
|
90 |
|
91 #my @valid_params = qw/Add-ons Distributor ProductName ReleaseChannel StartupTime UserID Version BuildID CrashTime Comments/; |
125 |
92 |
126 # save the dump in a file |
93 # save the dump in a file |
127 my $file = $self->req->upload('upload_file_minidump'); |
94 my $file = $self->req->upload('upload_file_minidump'); |
128 my %paramshash = map { $_ => $self->req->param($_) } $self->req->param; |
95 my %paramshash = map { $_ => $self->req->param($_) } $self->req->param; |
129 |
96 |
137 my $pjson = shift; |
104 my $pjson = shift; |
138 # reply |
105 # reply |
139 $self->render(text => $pjson->{status}); |
106 $self->render(text => $pjson->{status}); |
140 } |
107 } |
141 ); |
108 ); |
142 |
109 } => 'submit'; |
143 }; |
|
144 |
110 |
145 app->secrets([ |
111 app->secrets([ |
146 'My secret passphrase here' |
112 'My secret passphrase here' |
147 ]); |
113 ]); |
148 |
114 |
149 push @{app->commands->namespaces}, 'CrashTest::Commands'; |
115 push @{app->commands->namespaces}, 'CrashTest::Commands'; |
|
116 push @{app->plugins->namespaces}, 'CrashTest::Helpers'; |
|
117 |
|
118 plugin 'Config'; |
|
119 plugin 'TagHelpers::BootstrapPagination'; |
|
120 plugin 'CrashTestHelpers'; |
|
121 |
150 app->start; |
122 app->start; |