* Working on a file upload with progress bar feature. Expect more changes as it is refined.

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 6 years ago
parent 0979402ecf
commit d68b85fe9e
  1. 53
      Anvil/Tools/Get.pm
  2. 6
      Anvil/Tools/Job.pm
  3. 80
      cgi-bin/striker
  4. 73
      cgi-bin/upload.pl
  5. 147
      html/skins/alteeve/files.css
  6. 7
      html/skins/alteeve/files.html
  7. 21
      html/skins/alteeve/files.js
  8. 5
      share/words.xml

@ -203,24 +203,26 @@ sub cgi
# Needed to read in passed CGI variables # Needed to read in passed CGI variables
my $cgi = CGI->new(); my $cgi = CGI->new();
# The list of CGI variables to try and read will always be in 'cgi_list'.
my $cgis = []; my $cgis = [];
my $cgi_count = 0; my $cgi_count = 0;
if (defined $cgi->param("cgi_list")) # Get the list of parameters coming in, if possible,
if (exists $cgi->{param})
{ {
my $cgi_list = $cgi->param("cgi_list"); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { 'cgi->{param}' => $cgi->{param} }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { cgi_list => $cgi_list }}); foreach my $variable (sort {$a cmp $b} keys %{$cgi->{param}})
foreach my $variable (split/,/, $cgi_list)
{ {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { variable => $variable }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { variable => $variable }});
push @{$cgis}, $variable; push @{$cgis}, $variable;
} }
} }
elsif (exists $cgi->{param}) elsif (defined $cgi->param("cgi_list"))
{ {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { 'cgi->{param}' => $cgi->{param} }}); ### TODO: Get rid of this
foreach my $variable (sort {$a cmp $b} keys %{$cgi->{param}}) # This is a fall-back list we really shouldn't need.
my $cgi_list = $cgi->param("cgi_list");
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { cgi_list => $cgi_list }});
foreach my $variable (split/,/, $cgi_list)
{ {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { variable => $variable }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { variable => $variable }});
push @{$cgis}, $variable; push @{$cgis}, $variable;
@ -240,29 +242,36 @@ sub cgi
# Now read in the variables. # Now read in the variables.
foreach my $variable (sort {$a cmp $b} @{$cgis}) foreach my $variable (sort {$a cmp $b} @{$cgis})
{ {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { variable => $variable }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { variable => $variable }});
$anvil->data->{cgi}{$variable}{value} = ""; $anvil->data->{cgi}{$variable}{value} = "";
$anvil->data->{cgi}{$variable}{mimetype} = "string"; $anvil->data->{cgi}{$variable}{mime_type} = "string";
$anvil->data->{cgi}{$variable}{filehandle} = ""; $anvil->data->{cgi}{$variable}{file_handle} = "";
$anvil->data->{cgi}{$variable}{file_name} = "";
$anvil->data->{cgi}{$variable}{alert} = 0; # This is set if a sanity check fails $anvil->data->{cgi}{$variable}{alert} = 0; # This is set if a sanity check fails
if ($variable eq "file") # This is a special CGI key for download files (upload from the user's perspective)
if ($variable eq "upload_file")
{ {
if (not $cgi->upload($variable)) if (not $cgi->upload('upload_file'))
{ {
# Empty file passed, looks like the user forgot to select a file to upload. # Empty file passed, looks like the user forgot to select a file to upload.
#$anvil->Log->entry({log_level => $debug, message_key => "log_0016", file => $THIS_FILE, line => __LINE__}); $anvil->Log->entry({log_level => 2, message_key => "log_0242", file => $THIS_FILE, line => __LINE__});
} }
else else
{ {
$anvil->data->{cgi}{$variable}{filehandle} = $cgi->upload($variable); $anvil->data->{cgi}{upload_file}{file_handle} = $cgi->upload('upload_file');
my $file = $anvil->data->{cgi}{$variable}{filehandle}; my $file = $anvil->data->{cgi}{upload_file}{file_handle};
$anvil->data->{cgi}{$variable}{mimetype} = $cgi->uploadInfo($file)->{'Content-Type'}; $anvil->data->{cgi}{upload_file}{file_name} = $file;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { $anvil->data->{cgi}{upload_file}{mime_type} = $cgi->uploadInfo($file)->{'Content-Type'};
variable => $variable, $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
"cgi::${variable}::filehandle" => $anvil->data->{cgi}{$variable}{filehandle}, variable => 'upload_file',
"cgi::${variable}::mimetype" => $anvil->data->{cgi}{$variable}{mimetype}, "cgi::${variable}::file_handle" => $anvil->data->{cgi}{upload_file}{file_handle},
"cgi::${variable}::file_handle->handle" => $anvil->data->{cgi}{upload_file}{file_handle}->handle,
"cgi::${variable}::file_name" => $anvil->data->{cgi}{upload_file}{file_name},
"cgi::${variable}::mime_type" => $anvil->data->{cgi}{upload_file}{mime_type},
"cgi->upload('upload_file')" => $cgi->upload('upload_file'),
"cgi->upload('upload_file')->handle" => $cgi->upload('upload_file')->handle,
}}); }});
} }
} }

@ -216,16 +216,16 @@ WHERE
AND AND
job_host_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($anvil->Get->host_uuid)." job_host_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($anvil->Get->host_uuid)."
;"; ;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
my $job_count = $results->[0]->[0]; my $job_count = $results->[0]->[0];
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
results => $results, results => $results,
job_count => $job_count, job_count => $job_count,
}}); }});
my $jobs_running = $job_count ? 1 : 0; my $jobs_running = $job_count ? 1 : 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { jobs_running => $jobs_running }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { jobs_running => $jobs_running }});
return($jobs_running); return($jobs_running);
} }

@ -38,7 +38,15 @@ $anvil->data->{form}{back_link} = "";
$anvil->data->{form}{refresh_link} = ""; $anvil->data->{form}{refresh_link} = "";
# Read in any CGI variables, if needed. # Read in any CGI variables, if needed.
$anvil->Get->cgi(); $anvil->Get->cgi({debug => 2});
# If we're being asked to get a file, do so now.
if ($anvil->data->{cgi}{upload_file}{file_handle})
{
# Save and exit. We've got ajax handling the UI so this invocation only saves the file.
handle_upload($anvil);
$anvil->nice_exit({exit_code => 0});
}
# If the system hasn't initialized, there may be no host.uuid, and we'll need a better error to show the # If the system hasn't initialized, there may be no host.uuid, and we'll need a better error to show the
# user. # user.
@ -61,10 +69,12 @@ if (not $anvil->data->{sys}{database}{connections})
# If any jobs are pending/running, show the "unavailable" option. # If any jobs are pending/running, show the "unavailable" option.
my $configured = $anvil->System->check_if_configured; my $configured = $anvil->System->check_if_configured;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { configured => $configured }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { configured => $configured }});
### TODO: Something is causing fairly frequent resyncs, which results in Striker going in and out of
### maintenance mode.
my $available = $configured ? check_availability($anvil) : 0; my $available = $configured ? check_availability($anvil) : 0;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {available => $available }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {available => $available }});
if (not $configured) if (not $configured)
{ {
# If there is no user account yet, then the system is new and needs to be reconfigured. # If there is no user account yet, then the system is new and needs to be reconfigured.
@ -99,6 +109,64 @@ print_and_exit($anvil);
# Functions # # Functions #
############################################################################################################# #############################################################################################################
# This handles uploading (downloading by our perspective)
sub handle_upload
{
my ($anvil) = @_;
# Get the file handle.
my $cgi_file_handle = $anvil->data->{cgi}{upload_file}{file_handle};
my $file_name = $anvil->data->{cgi}{upload_file}{file_name};
my $mime_type = $anvil->data->{cgi}{upload_file}{mime_type};
my $output_file = $anvil->data->{path}{directories}{shared}{incoming}."/".$file_name;
$output_file =~ s/\/\//\//g;
# TODO: Make sure characters like spaces and whatnot don't need to be escaped.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
cgi_file_handle => $cgi_file_handle,
file_name => $file_name,
mime_type => $mime_type,
output_file => $output_file,
}});
open (my $file_handle, ">", $output_file) or $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0015", variables => { shell_call => $output_file, error => $! }});
binmode $file_handle;
while(<$file_handle>)
{
print $cgi_file_handle $_;
}
close $file_handle;
if (not -f $output_file)
{
# Something went wrong
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "alert", key => "log_0257", variables => { file => $output_file }});
}
else
{
# Looks like we got it.
my $file_size = -s $output_file;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file_size => $file_size }});
if (not $file_size)
{
# Looks like we didn't actually get the file...
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "alert", key => "log_0258", variables => { file => $output_file }});
unlink $output_file;
}
else
{
my $say_size_in_bytes = $anvil->Convert->add_commas({number => $file_size});
my $say_human_size = $anvil->Convert->bytes_to_human_readable({'bytes' => $file_size});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0256", variables => {
file => $output_file,
size_in_bytes => $say_size_in_bytes,
human_readable_size => $say_human_size,
}});
}
}
return(0);
}
sub print_and_exit sub print_and_exit
{ {
my ($anvil) = @_; my ($anvil) = @_;
@ -130,8 +198,8 @@ sub print_and_exit
# The jobs button is "on" when the user is logged in and there is one or more jobs on this system # The jobs button is "on" when the user is logged in and there is one or more jobs on this system
# under 100% complete. # under 100% complete.
my $say_jobs_button = $anvil->Template->get({file => "main.html", name => "jobs_button_off"}); my $say_jobs_button = $anvil->Template->get({file => "main.html", name => "jobs_button_off"});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_jobs_button => $say_jobs_button }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { say_jobs_button => $say_jobs_button }});
if (($anvil->data->{sys}{users}{user_name}) && ($anvil->Job->running({debug => 2}))) if (($anvil->data->{sys}{users}{user_name}) && ($anvil->Job->running({debug => 3})))
{ {
$say_jobs_button = $anvil->Template->get({file => "main.html", name => "jobs_button_on"}); $say_jobs_button = $anvil->Template->get({file => "main.html", name => "jobs_button_on"});
} }
@ -1205,7 +1273,7 @@ sub check_availability
{ {
my ($anvil) = @_; my ($anvil) = @_;
my $debug = 2; my $debug = 3;
my $available = 1; my $available = 1;
# Check maintenance mode. # Check maintenance mode.

@ -0,0 +1,73 @@
#!/usr/bin/perl
use strict;
use warnings;
use CGI;
my $cgi = CGI->new;
print q|Content-type: text/html; charset=utf-8
<!DOCTYPE html>
<html lang="en_CA">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- Disable caching during development. -->
<meta http-equiv="cache-control" content="max-age=0" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
<meta http-equiv="pragma" content="no-cache" /> <title>Alteeve - Striker</title>
<link rel="stylesheet" href="/skins/alteeve/main.css" media="screen" />
<script type="text/javascript" src="/jquery-latest.js"></script>
<script type="text/javascript" src="/skins/alteeve/main.js"></script>
<!-- NOTE: These are for jquery-ui using the 'smoothness' skin. We may want to move this under the skin directory in case other skins want to use different jquery-ui skins someday. -->
<link rel="stylesheet" href="/jquery-ui-latest/jquery-ui.css">
<script type="text/javascript" src="/jquery-ui-latest/jquery-ui.js"></script>
<script type="text/javascript" src="/skins/alteeve/files.js"></script>
<link rel="stylesheet" href="/skins/alteeve/files.css">
|;
my $lightweight_fh = $cgi->upload('field_name');
# undef may be returned if it's not a valid file handle
if ($cgi->param())
{
print q|
<title>Saving File...</title>
</head>
<body>
|;
my $filename = $cgi->upload('upload_file');
my $out = "/mnt/shared/incoming/".$filename;
print "Saving file: [".$out."]\n";
my $cgi_file_handle = $cgi->param('upload_file');
open(my $file_handle, ">$out") or die "failed to write: [$out], error: $!\n";
while(<$cgi_file_handle>)
{
print $file_handle $_;
}
close $file_handle;
print "Done.\n";
}
else
{
print q|
<title>Test Upload</title>
</head>
<body>
<h1>Upload file</h1>
<form method="post" enctype="multipart/form-data">
<!-- <input type="file" name="upload_file" value="Choose file"> -->
<!-- <input type="submit" name="submit" value="Upload"> -->
Upload
<div id="fileuploader">Upload</div>
</form>
|;
}
print "</body>\n";
exit(0);

@ -0,0 +1,147 @@
/* From: http://hayageek.github.io/jQuery-Upload-File/4.0.11/uploadfile.css */
.ajax-file-upload-statusbar {
border: 1px solid #0ba1b5;
margin-top: 10px;
width: 420px;
margin-right: 10px;
margin: 5px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
padding: 5px 5px 5px 15px
}
.ajax-file-upload-filename {
width: 300px;
height: auto;
margin: 0 5px 5px 0px;
}
.ajax-file-upload-filesize {
width: 50px;
height: auto;
margin: 0 5px 5px 0px;
display: inline-block;
vertical-align:middle;
}
.ajax-file-upload-progress {
margin: 5px 10px 5px 0px;
position: relative;
width: 250px;
border: 1px solid #ddd;
padding: 1px;
border-radius: 3px;
display: inline-block;
color:#FFFFFF;
}
.ajax-file-upload-bar {
background-color: #0ba1b5;
width: 0;
height: 20px;
border-radius: 3px;
color:#FFFFFF;
}
.ajax-file-upload-percent {
position: absolute;
display: inline-block;
top: 3px;
left: 48%
}
.ajax-file-upload-red {
-moz-box-shadow: inset 0 39px 0 -24px #e67a73;
-webkit-box-shadow: inset 0 39px 0 -24px #e67a73;
box-shadow: inset 0 39px 0 -24px #e67a73;
background-color: #e4685d;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
display: inline-block;
color: #fff;
font-family: arial;
font-size: 13px;
font-weight: normal;
padding: 4px 15px;
text-decoration: none;
text-shadow: 0 1px 0 #b23e35;
cursor: pointer;
vertical-align: top;
margin: 5px 10px 5px 0px;
}
.ajax-file-upload-green {
background-color: #77b55a;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
margin: 0;
padding: 0;
display: inline-block;
color: #fff;
font-family: arial;
font-size: 13px;
font-weight: normal;
padding: 4px 15px;
text-decoration: none;
cursor: pointer;
text-shadow: 0 1px 0 #5b8a3c;
vertical-align: top;
margin: 5px 10px 5px 0px;
}
.ajax-file-upload {
font-family: Arial, Helvetica, sans-serif;
font-size: 16px;
font-weight: bold;
padding: 15px 20px;
cursor:pointer;
line-height:20px;
height:25px;
margin:0 10px 10px 0;
display: inline-block;
background: #fff;
border: 1px solid #e8e8e8;
color: #888;
text-decoration: none;
border-radius: 3px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
-moz-box-shadow: 0 2px 0 0 #e8e8e8;
-webkit-box-shadow: 0 2px 0 0 #e8e8e8;
box-shadow: 0 2px 0 0 #e8e8e8;
padding: 6px 10px 4px 10px;
color: #fff;
background: #2f8ab9;
border: none;
-moz-box-shadow: 0 2px 0 0 #13648d;
-webkit-box-shadow: 0 2px 0 0 #13648d;
box-shadow: 0 2px 0 0 #13648d;
vertical-align: middle;
}
.ajax-file-upload:hover {
background: #3396c9;
-moz-box-shadow: 0 2px 0 0 #15719f;
-webkit-box-shadow: 0 2px 0 0 #15719f;
box-shadow: 0 2px 0 0 #15719f;
}
.ajax-upload-dragdrop
{
border:2px dotted #A5A5C7;
width:420px;
color: #DADCE3;
text-align:left;
vertical-align:middle;
padding:10px 10px 0px 10px;
}
.state-hover
{
border:2px solid #A5A5C7;
}
.ajax-file-upload-container
{
margin:20px 0px 20px 0px;
}

@ -1,5 +1,8 @@
<!-- start main-menu --> <!-- start main-menu -->
<table align="center" class="anvil_main_menu"> <table align="center" class="anvil_main_menu">
<script type="text/javascript" src="#!data!skin::url!#/files.js"></script>
<link rel="stylesheet" href="#!data!skin::url!#/files.css">
<form method="post" enctype="multipart/form-data">
<tr> <tr>
<td colspan="2"> <td colspan="2">
&nbsp; &nbsp;
@ -17,8 +20,10 @@
</tr> </tr>
<tr> <tr>
<td> <td>
Upload file. Upload
<div id="fileuploader">Upload</div>
</td> </td>
</tr> </tr>
</form>
</table> </table>
<!-- end main-menu --> <!-- end main-menu -->

File diff suppressed because one or more lines are too long

@ -527,7 +527,7 @@ The body of the file: [#!variable!file!#] does not match the new body. The file
<key name="log_0239">'Install Target' job: [#!data!switches::job-uuid!#] picked up.</key> <key name="log_0239">'Install Target' job: [#!data!switches::job-uuid!#] picked up.</key>
<key name="log_0240">'Install Target' job: [#!data!switches::job-uuid!#] aborted, system not yet configured.</key> <key name="log_0240">'Install Target' job: [#!data!switches::job-uuid!#] aborted, system not yet configured.</key>
<key name="log_0241">Package list loaded.</key> <key name="log_0241">Package list loaded.</key>
<key name="log_0242">#!free!#</key> <key name="log_0242">It looks like a user tried to upload a file without actually doing so.</key>
<key name="log_0243">[ Error ] - Failed to delete the file: [#!variable!file!#].</key> <key name="log_0243">[ Error ] - Failed to delete the file: [#!variable!file!#].</key>
<key name="log_0244">[ Warning ] - None of the databases are accessible. ScanCore will try to connect once a minute until a database is accessible.</key> <key name="log_0244">[ Warning ] - None of the databases are accessible. ScanCore will try to connect once a minute until a database is accessible.</key>
<key name="log_0245">[ Cleared ] - We now have databases accessible, proceeding.</key> <key name="log_0245">[ Cleared ] - We now have databases accessible, proceeding.</key>
@ -544,6 +544,9 @@ The md5sum of: [#!variable!file!#] has changed since the daemon started.
<key name="log_0253">The database user is not 'admin'. Changing table and function ownerships to: [#!variable!database_user!#].</key> <key name="log_0253">The database user is not 'admin'. Changing table and function ownerships to: [#!variable!database_user!#].</key>
<key name="log_0254">[ Warning ] - The Storage->make_directory() method failed to create the directory: [#!variable!directory!#].</key> <key name="log_0254">[ Warning ] - The Storage->make_directory() method failed to create the directory: [#!variable!directory!#].</key>
<key name="log_0255">[ Note ] - Created the directory: [#!variable!directory!#].</key> <key name="log_0255">[ Note ] - Created the directory: [#!variable!directory!#].</key>
<key name="log_0256">[ Note ] - Downloaded: [#!variable!file!#] (#!variable!human_readable_size!# / #!variable!size_in_bytes!# bytes).</key>
<key name="log_0257">[ Warning ] - It appears that we failed to downloaded and save: [#!variable!file!#].</key>
<key name="log_0258">[ Warning ] - It appears that we failed to downloaded and save: [#!variable!file!#]. The output file has no size, and will be removed.</key>
<!-- Test words. Do NOT change unless you update 't/Words.t' or tests will needlessly fail. --> <!-- Test words. Do NOT change unless you update 't/Words.t' or tests will needlessly fail. -->
<key name="t_0000">Test</key> <key name="t_0000">Test</key>

Loading…
Cancel
Save