diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..5ceb3864 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +venv diff --git a/easyinstall.sh b/easyinstall.sh index c3535c45..a3701188 100755 --- a/easyinstall.sh +++ b/easyinstall.sh @@ -34,7 +34,7 @@ function initialChecks() { fi if [ ! -d ~/RASCSI ]; then - echo "You must checkout RASCSI repo into /user/pi/RASCSI" + echo "You must checkout RASCSI repo into /home/pi/RASCSI" echo "$ git clone git@github.com:akuker/RASCSI.git" exit 2 fi @@ -46,9 +46,9 @@ function initialChecks() { function installRaScsi() { sudo apt-get update && sudo apt-get install --yes git libspdlog-dev - cd ~/RASCSI/src/raspberrypi - make all CONNECT_TYPE=FULLSPEC - sudo make install CONNECT_TYPE=FULLSPEC + cd ~/RASCSI/src/raspberrypi + make all CONNECT_TYPE=FULLSPEC + sudo make install CONNECT_TYPE=FULLSPEC sudoIsReady=$(sudo grep -c "rascsi" /etc/sudoers) @@ -61,35 +61,28 @@ www-data ALL=NOPASSWD: /bin/systemctl stop rascsi.service www-data ALL=NOPASSWD: /sbin/shutdown, /sbin/reboot " >> /etc/sudoers' fi - - sudo systemctl restart rsyslog - sudo systemctl enable rascsi # optional - start rascsi at boot - sudo systemctl start rascsi - + + sudo systemctl restart rsyslog + sudo systemctl enable rascsi # optional - start rascsi at boot + sudo systemctl start rascsi } -# install everything required to run an HTTP server (Apache+PHP) -# configure PHP -# install +function stopOldWebInterface() { + APACHE_STATUS=$(sudo systemctl status apache2 &> /dev/null; echo $?) + if [ $APACHE_STATUS -eq 0 ] ; then + echo "Stopping old Apache2 RaSCSI Web..." + sudo systemctl disable apache2 + sudo systemctl stop apache2 + fi +} + +# install everything required to run an HTTP server (Nginx + Python Flask App) function installRaScsiWebInterface() { - - sudo apt install apache2 php libapache2-mod-php -y - - sudo cp ~/RASCSI/src/php/* /var/www/html + stopOldWebInterface + sudo apt install genisoimage python3 python3-venv nginx -y - - PHP_CONFIG_FILE=/etc/php/7.3/apache2/php.ini - - #Comment out any current configuration - sudo sed -i.bak 's/^post_max_size/#post_max_size/g' $PHP_CONFIG_FILE - sudo sed -i.bak 's/^upload_max_filesize/#upload_max_filesize/g' $PHP_CONFIG_FILE - - sudo bash -c 'PHP_CONFIG_FILE=/etc/php/7.3/apache2/php.ini && echo " -# RaSCSI high upload limits -upload_max_filesize = 1200M -post_max_size = 1200M - -" >> $PHP_CONFIG_FILE' + sudo cp -f ~/RASCSI/src/web/service-infra/nginx-default.conf /etc/nginx/sites-available/default + sudo cp -f ~/RASCSI/src/web/service-infra/502.html /var/www/html/502.html mkdir -p $VIRTUAL_DRIVER_PATH chmod -R 775 $VIRTUAL_DRIVER_PATH @@ -97,30 +90,38 @@ post_max_size = 1200M sudo usermod -a -G pi www-data groups www-data - sudo /etc/init.d/apache2 restart + sudo systemctl reload nginx + + sudo cp ~/RASCSI/src/web/service-infra/rascsi-web.service /etc/systemd/system/rascsi-web.service + sudo systemctl daemon-reload + sudo systemctl enable rascsi-web + sudo systemctl start rascsi-web } - +function updateRaScsiGit() { + cd ~/RASCSI + git pull +} function updateRaScsi() { + updateRaScsiGit sudo systemctl stop rascsi - cd ~/RASCSI/src/raspberrypi - - make clean - make all CONNECT_TYPE=FULLSPEC - sudo make install CONNECT_TYPE=FULLSPEC - sudo systemctl start rascsi + cd ~/RASCSI/src/raspberrypi + + make clean + make all CONNECT_TYPE=FULLSPEC + sudo make install CONNECT_TYPE=FULLSPEC + sudo systemctl start rascsi } function updateRaScsiWebInterface() { - sudo /etc/init.d/apache2 stop - cd ~/RASCSI - git fetch --all - cd ~/RASCSI/src/raspberrypi - sudo cp ~/RASCSI/src/php/* /var/www/html - - sudo /etc/init.d/apache2 start + stopOldWebInterface + updateRaScsiGit + sudo cp -f ~/RASCSI/src/web/service-infra/nginx-default.conf /etc/nginx/sites-available/default + sudo cp -f ~/RASCSI/src/web/service-infra/502.html /var/www/html/502.html + sudo systemctl restart rascsi-web + sudo systemctl restart nginx } function showRaScsiStatus() { diff --git a/src/php/.editorconfig b/src/php/.editorconfig deleted file mode 100644 index d03ab4e6..00000000 --- a/src/php/.editorconfig +++ /dev/null @@ -1,8 +0,0 @@ -root = true - -[*.{html,php,htm}] -indent_style = space -indent_size = 3 -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true diff --git a/src/php/LICENSE b/src/php/LICENSE deleted file mode 100644 index ffef9a2f..00000000 --- a/src/php/LICENSE +++ /dev/null @@ -1,31 +0,0 @@ -BSD 3-Clause License - -Copyright (C) 2001-2006 PI.(ytanaka@ipc-tokai.or.jp) -Copyright (C) 2014-2020 GIMONS -Copyright (c) 2020, akuker -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/php/concept_wireframe.png b/src/php/concept_wireframe.png deleted file mode 100644 index 1aea0024..00000000 Binary files a/src/php/concept_wireframe.png and /dev/null differ diff --git a/src/php/lib_rascsi.php b/src/php/lib_rascsi.php deleted file mode 100644 index fb483a47..00000000 --- a/src/php/lib_rascsi.php +++ /dev/null @@ -1,260 +0,0 @@ - - - - - - -'. PHP_EOL; - echo ' '. PHP_EOL; - echo '

RaSCSI - 68kmla Edition

'. PHP_EOL; - echo ' '. PHP_EOL; - echo '
'. PHP_EOL; - echo ' '. PHP_EOL; - if($GLOBALS['DEBUG_ENABLE']){ - echo '

Debug Timestamp: '.time().'

'. PHP_EOL; - } - echo '
'. PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - //echo(exec('whoami')); -} - -function html_generate_image_file_select_list(){ - $all_files = get_all_files(); - foreach(explode(PHP_EOL, $all_files) as $this_file){ - if(strpos($this_file, 'total') === 0){ - continue; - } - $file_name = file_name_from_ls($this_file); - if(strlen($file_name) === 0){ - continue; - } - // Ignore files that start with a . - if(strpos($file_name, '.') === 0){ - continue; - } - - echo ''.PHP_EOL; - } -} - - -function html_generate_scsi_id_select_list(){ - echo ''. PHP_EOL; -} - -function html_generate_scsi_type_select_list(){ - echo ''. PHP_EOL; -} - -function html_generate_warning($message){ - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo '
'. PHP_EOL; - echo ' '.$message.''. PHP_EOL; - echo '
'. PHP_EOL; -} - -function html_generate_success_message($message){ - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - if(strlen($message) > 0){ - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - } - echo '
'. PHP_EOL; - echo ' Success'. PHP_EOL; - echo '
'. PHP_EOL; - echo ' '.$message.PHP_EOL; - echo '
'. PHP_EOL; -} - -function html_generate_ok_to_go_home(){ - echo '
'. PHP_EOL; - echo ' '. PHP_EOL; - echo '
'. PHP_EOL; -} - - -function current_rascsi_config() { - $raw_output = shell_exec("/usr/local/bin/rasctl -l"); - $rasctl_lines = explode(PHP_EOL, $raw_output); - - echo '
'. PHP_EOL; - echo '

Current RaSCSI Configuration

'. PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - - $scsi_ids = array(); - - foreach ($rasctl_lines as $current_line) - { - if(strlen($current_line) === 0){ - continue; - } - if(strpos($current_line, '+----') === 0){ - continue; - - } - if(strpos($current_line, '| ID | UN') === 0){ - continue; - } - $segments = explode("|", $current_line); - - $id_config = array(); - $id_config['id'] = trim($segments[1]); - $id_config['type'] = trim($segments[3]); - $id_config['file'] = trim($segments[4]); - - $scsi_ids[$id_config['id']] = $id_config; - } - - - foreach (range(0,7) as $id){ - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - if(isset($scsi_ids[$id])) - { - echo ' '. PHP_EOL; - if(strtolower($scsi_ids[$id]['file']) == "no media"){ - echo ' '.PHP_EOL; - } - else{ - // rascsi inserts "WRITEPROTECT" for the read-only drives. We want to display that differently. - echo ' '. PHP_EOL; - echo ' '.PHP_EOL; - echo ' '. PHP_EOL; - } - echo ' '. PHP_EOL; - } - else - { - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - - } - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - } - echo '
SCSI IDTypeFileFile OpsDevice Ops
'.$id.''.$scsi_ids[$id]['type'].''.PHP_EOL; - echo '
'. PHP_EOL; - echo ' '.PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo '
'.PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo '
'.str_replace('(WRITEPROTECT)', '', $scsi_ids[$id]['file']). PHP_EOL; - echo ' '.PHP_EOL; - if(strtolower($scsi_ids[$id]['type']) == 'sccd'){ - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - } - echo ' '. PHP_EOL; - echo '
'. PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo '
'. PHP_EOL; - echo '
--'. PHP_EOL; - echo '
'. PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo ' '. PHP_EOL; - echo '
'. PHP_EOL; - echo '
'. PHP_EOL; -} -function get_all_files() -{ - $raw_ls_output = shell_exec('ls --time-style="+\"%Y-%m-%d %H:%M:%S\"" -alh --quoting-style=c '.$GLOBALS['FILE_PATH']); - return $raw_ls_output; -} - -function mod_date_from_ls($value){ - $ls_pieces = explode("\"", $value); - if(count($ls_pieces)<1){ - return ""; - } - return $ls_pieces[1]; -} -function file_name_from_ls($value){ - $ls_pieces = explode("\"", $value); - if(count($ls_pieces) < 4){ - return ""; - } - return $ls_pieces[3]; -} -function file_size_from_ls($value){ - $ls_pieces = explode("\"", $value); - $file_props = preg_split("/\s+/", $ls_pieces[0]); - return $file_props[4]; -} -function file_category_from_file_name($value){ - if(strpos($value,".iso") || strpos($value,".cdr") > 0){ - return "CD-ROM Image"; - } - if(strpos($value,".hda") > 0){ - return "Hard Disk Image"; - } - return "Unknown type: " . $value; -} - - - -function type_string_to_rasctl_type($typestr){ - if(strcasecmp($typestr,"Hard Disk") == 0){ - return "hd"; - } - if(strcasecmp($typestr,"CD-ROM") == 0){ - return "cd"; - } - if(strcasecmp($typestr,"Zip Drive") == 0){ - } - if(strcasecmp($typestr,"Filesystem bridge") == 0){ - return "bridge"; - } - return ""; -} - - - - -?> diff --git a/src/php/rascsi.html b/src/php/rascsi.html deleted file mode 100644 index 2dac00d6..00000000 --- a/src/php/rascsi.html +++ /dev/null @@ -1,9 +0,0 @@ - - RaSCSI Control Page - - - - You must use a browser that can display frames - to see this page. - - diff --git a/src/php/rascsi.php b/src/php/rascsi.php deleted file mode 100644 index f18d2b97..00000000 --- a/src/php/rascsi.php +++ /dev/null @@ -1,135 +0,0 @@ - - - - - - - - - - - RaSCSI Main Control Page - - - - - - - -
-

Image File Management

- - - - - - - - - - - '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ''.PHP_EOL; - } -?> -
LocationFilenameSizeTypeDate ModifiedActions
SD Card'.$file_name.''.file_size_from_ls($this_file).''.file_category_from_file_name($file_name).''.mod_date_from_ls($this_file).''.PHP_EOL; - echo '
'.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo '
'.PHP_EOL; - echo '
- - -
-
-

Upload New Image File

-
- - - - - -
-

-
- -
-
- -
-

Create New Empty HD Image

-
- - -
- -
-

RaSCSI Service Status

- - - - - -
-
- - -
-
-
- - -
-
- -
-

Raspberry Pi Operations

- - - - - -
-
- - -
-
-
- - -
-
- - - - diff --git a/src/php/rascsi_action.php b/src/php/rascsi_action.php deleted file mode 100644 index ec6740ad..00000000 --- a/src/php/rascsi_action.php +++ /dev/null @@ -1,297 +0,0 @@ - - - - - - - - RaSCSI Action Page - - - - - '; - if($GLOBALS['DEBUG_ENABLE']){ - echo ''.PHP_EOL; - echo ' '.PHP_EOL; - echo '

Debug stuff

'; - - echo '

Post values......................'.PHP_EOL; - echo '
'.PHP_EOL; - var_dump($_POST); - echo '

Running command.... '.$_POST['command'].PHP_EOL; - echo '

'.PHP_EOL; - echo '
'; - } - - if(isset($_POST['command'])) - { - switch(strtolower($_POST['command'])){ - case "eject_disk": - action_eject_disk(); - break; - case "remove_device": - action_remove_device(); - break; - case "connect_new_device": - action_connect_new_device(); - break; - case "insert_disk": - action_insert_disk(); - break; - case "delete_file": - action_delete_file(); - break; - case "create_new_image": - action_create_new_image(); - break; - case "restart_rascsi_service": - action_restart_rascsi_service(); - break; - case "stop_rascsi_service": - action_stop_rascsi_service(); - break; - case "reboot_raspberry_pi": - action_reboot_raspberry_pi(); - break; - case "shutdown_raspberry_pi": - action_shutdown_raspberry_pi(); - break; - default: - action_unknown_command(); - break; - } - } - else{ - html_generate_warning("HTTP command was missing POST information. Are you trying to access this page directly? That won't work"); - echo "
".PHP_EOL; - html_generate_ok_to_go_home(); - } - -function action_eject_disk(){ - $command = 'rasctl -i '.$_POST['id'].' -c eject 2>&1'.PHP_EOL; - exec($command, $retArray, $result); - check_result($result, $command,$retArray); - html_generate_ok_to_go_home(); -} - -function action_remove_device(){ - // Check to see if the user has confirmed - if(isset($_POST['confirmed'])){ - $command = 'rasctl -i '.$_POST['id'].' -c disconnect 2>&1'.PHP_EOL; - exec($command, $retArray, $result); - check_result($result, $command,$retArray); - html_generate_ok_to_go_home(); - } - else{ - check_are_you_sure('Are you sure you want to disconnect SCSI ID ' . $_POST['id'].'? If the host is running, this could cause undesirable behavior.'); - } -} -// function action_connect_new_device(){} -function action_insert_disk(){ - $command = 'rasctl -i '.$_POST['id'].' -c insert -f '.$GLOBALS['FILE_PATH'].'/'.$_POST['file_name'].' 2>&1'.PHP_EOL; - exec($command, $retArray, $result); - check_result($result, $command,$retArray); - html_generate_ok_to_go_home(); -} -function action_create_new_image(){ - // If we already know the size & filename, we can go create the image... - if(isset($_POST['size']) && isset($_POST['file_name'])){ - $command = 'dd if=/dev/zero of='.$GLOBALS['FILE_PATH'].'/'.$_POST['file_name'].' bs=1M count='.$_POST['size']; - exec($command, $retArray, $result); - check_result($result, $command, $retArray); - html_generate_ok_to_go_home(); - } - else{ - echo '

Create a new empty file

'.PHP_EOL; - echo '
'.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo '
File Name:'.PHP_EOL; - echo ' '.PHP_EOL; - echo ' Size:'.PHP_EOL; - echo ' '.PHP_EOL; - echo ' MB'.PHP_EOL; - echo ' '.PHP_EOL; - echo '
'.PHP_EOL; - echo '
'.PHP_EOL; - echo '
Note: Creating a large file may take a long time!'.PHP_EOL; - echo '

'.PHP_EOL; - echo '
'.PHP_EOL; - echo ' '.PHP_EOL; - echo '
'.PHP_EOL; - } -} - -function action_delete_file(){ - // Check to see if the user has confirmed - if(isset($_POST['confirmed'])){ - $command = 'rm '.$GLOBALS['FILE_PATH'].'/'.$_POST['file_name']; - exec($command, $retArray, $result); - check_result($result, $command, $retArray); - html_generate_ok_to_go_home(); - } - else{ - check_are_you_sure('Are you sure you want to PERMANENTLY delete '.$_POST['file_name'].'?'); - } -} - -function action_restart_rascsi_service(){ - // Restart the RaSCSI service - $command = "sudo /bin/systemctl restart rascsi.service 2>&1"; - exec($command, $retArray, $result); - check_result($result, $command,$retArray); - html_generate_ok_to_go_home(); -} - -function action_stop_rascsi_service(){ - // Stop the RaSCSI service - $command = "sudo /bin/systemctl stop rascsi.service 2>&1"; - exec($command, $retArray, $result); - check_result($result, $command,$retArray); - html_generate_ok_to_go_home(); -} - -function action_reboot_raspberry_pi(){ - // Check to see if the user has confirmed - if(isset($_POST['confirmed'])){ - $command = "sleep 2 && sudo reboot 2>&1"; - exec($command, $retArray, $result); - // The unit should reboot at this point. Doesn't matter what we do now... - check_result($result, $command,$retArray); - html_generate_ok_to_go_home(); - } - else{ - check_are_you_sure("Are you sure you want to reboot the Raspberry Pi?"); - } -} - -function action_shutdown_raspberry_pi(){ - // Check to see if the user has confirmed - if(isset($_POST['confirmed'])){ - $command = "sleep 2 && sudo shutdown -h now 2>&1"; - exec($command, $retArray, $result); - // The unit should shutdown at this point. Doesn't matter what we do now... - check_result($result, $command,$retArray); - html_generate_ok_to_go_home(); - } - else{ - check_are_you_sure("Are you sure you want to shut down the Raspberry Pi?"); - } -} - -function action_unknown_command(){ - html_generate_warning('

Unknown command: '.$_POST['command'].'

'); - html_generate_ok_to_go_home(); -} - -function check_result($result,$command,$output){ - if(!$result){ - html_generate_success_message('Command succeeded!'); - } - else{ - html_generate_warning('Command failed!'); - } - echo '
'.$command.'
'.PHP_EOL; - if(count($output) > 0){ - echo '
Output:'.PHP_EOL; - foreach($output as $line){ - echo '
Error message: '.$line.PHP_EOL; - } - echo '
'.PHP_EOL; - } -} - -function check_are_you_sure($prompt){ - echo '

'.$prompt.'

'.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo '
'.PHP_EOL; - echo '
'.PHP_EOL; - foreach($_POST as $key => $value){ - echo ''.PHP_EOL; - } - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo '
'.PHP_EOL; - echo '
'.PHP_EOL; - echo '
'.PHP_EOL; - echo ' '.PHP_EOL; - echo '
'.PHP_EOL; - echo '
'.PHP_EOL; -} - -function action_connect_new_device(){ - // If we already know the type & filename, we can go connect the device... - if(isset($_POST['type']) && isset($_POST['file_name'])){ - $command = 'rasctl -i '.$_POST['id'].' -c attach -t '.type_string_to_rasctl_type($_POST['type']); - if($_POST['file_name'] != "None"){ - $command = $command.' -f '.$GLOBALS['FILE_PATH'].'/'.$_POST['file_name']; - } - exec($command, $retArray, $result); - check_result($result, $command, $retArray); - html_generate_ok_to_go_home(); - } - else{ - - - $id = $_POST['id']; - echo '

Add New Device

'.PHP_EOL; - echo '
'.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo '
SCSI ID:'.PHP_EOL; - echo ' '.PHP_EOL; - echo $id; - echo ' Device:'.PHP_EOL; - html_generate_scsi_type_select_list(); - echo ' File:'.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo ' '.PHP_EOL; - echo '
'.PHP_EOL; - } -} - -function get_new_filename(){ - // Try to find a new file name that doesn't exist. - $i=1; - while(file_exists($GLOBALS['FILE_PATH'].'/'.'new_file'.$i.'.hda')) - { - $i = $i+1; - } - return 'new_file'.$i.'.hda'; -} - -?> - - - - diff --git a/src/php/rascsi_upload.php b/src/php/rascsi_upload.php deleted file mode 100644 index e34fba89..00000000 --- a/src/php/rascsi_upload.php +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - RaSCSI Upload Page - - - - - '; - - if($GLOBALS['DEBUG_ENABLE']){ - echo ''.PHP_EOL; - echo ' '.PHP_EOL; - echo '

Debug stuff

'; - - echo '

Post values......................'.PHP_EOL; - echo '
'.PHP_EOL; - var_dump($_POST); - echo '

'.PHP_EOL; - var_dump($_FILES); - echo '

'.PHP_EOL; - echo '
'; - } - - $target_dir = $GLOBALS['FILE_PATH'].'/'; - $target_file = $target_dir.basename($_FILES['file_name']['name']); - $upload_ok=1; - $file_type = strtolower(pathinfo($target_file,PATHINFO_EXTENSION)); - - if(isset($_POST['submit'])) - { - // Check if file already exists - if ($upload_ok && (file_exists($target_file))) { - html_generate_warning('Error: File '.$target_file.' already exists.'); - $upload_ok = 0; - } - - // Check file size. Limit is specified in lib_rascsi.php - if ($upload_ok && ($_FILES["file_name"]["size"] > $GLOBALS['MAX_UPLOAD_FILE_SIZE'])) { - html_generate_warning("Error: your file is larger than the maximum size of " . $GLOBALS['MAX_UPLOAD_FILE_SIZE'] . "bytes"); - $upload_ok = 0; - } - - // Allow certain file formats, also specified in lib_rascsi.php - if($upload_ok && (!in_array(strtolower($file_type),$GLOBALS['ALLOWED_FILE_TYPES']))){ - $error_string = 'File type "'. $file_type. '" is not currently allowed.'. - 'Only the following file types are allowed:
'. - ''; - $error_string = $error_string.'
'; - html_generate_warning($error_string); - $upload_ok = 0; - } - - //Check if $upload_ok is set to 0 by an error - if ($upload_ok != 0) { - if (move_uploaded_file($_FILES["file_name"]["tmp_name"], $target_file)) { - html_generate_success_message(basename( $_FILES["file_name"]["name"]). " has been uploaded."); - } else { - html_generate_warning("There was an unknown error uploading your file."); - } - } - } - else - { - html_generate_warning('The Submit POST information was not populated. Something went wrong'); - } - echo '
'; - - html_generate_ok_to_go_home(); -?> - - - - diff --git a/src/php/status.php b/src/php/status.php deleted file mode 100644 index d49beefc..00000000 --- a/src/php/status.php +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - -'; - echo ''; - echo ''; - echo ''; - echo ''; - echo '
'.$text.' '.date("h:i:sa").'
'; -?> - - diff --git a/src/web/README.md b/src/web/README.md new file mode 100644 index 00000000..82088ba2 --- /dev/null +++ b/src/web/README.md @@ -0,0 +1,12 @@ +# RaSCSI Web + +## Mocking for local development + +Set a few env vars to point to the mock scripts and base dir + +``` +BASE_DIR=/tmp/images/ +PATH=$PATH:`pwd`/mock/bin/ +``` + +Edit response to commands in `mock/bin/*` diff --git a/src/web/create_disk.py b/src/web/create_disk.py new file mode 100644 index 00000000..2958c69d --- /dev/null +++ b/src/web/create_disk.py @@ -0,0 +1,45 @@ +from machfs import Volume, Folder, File + +from settings import * + + +# Build a cd and attempt to fix resource forks if known +def make_cd(file_path, file_type, file_creator): + with open(file_path, "rb") as f: + file_bytes = f.read() + file_name = file_path.split('/')[-1] + file_suffix = file_name.split('.')[-1] + + if file_type is None and file_creator is None: + if file_suffix.lower() == 'sea': + file_type = '.sea' + file_creator = 'APPL' + + v = Volume() + v.name = "TestName" + + v['Folder'] = Folder() + + v['Folder'][file_name] = File() + v['Folder'][file_name].data = file_bytes + v['Folder'][file_name].rsrc = b'' + if not (file_type is None and file_creator is None): + v['Folder'][file_name].type = bytearray(file_type) + v['Folder'][file_name].creator = bytearray(file_creator) + + padding = (len(file_bytes) % 512) + (512 * 50) + print("mod", str(len(file_bytes) % 512)) + print("padding " + str(padding)) + print("len " + str(len(file_bytes))) + print("total " + str(len(file_bytes) + padding)) + with open(base_dir + 'test.hda', 'wb') as f: + flat = v.write( + size=len(file_bytes) + padding, + align=512, # Allocation block alignment modulus (2048 for CDs) + desktopdb=True, # Create a dummy Desktop Database to prevent a rebuild on boot + bootable=False, # This requires a folder with a ZSYS and a FNDR file + startapp=('Folder', file_name), # Path (as tuple) to an app to open at boot + ) + f.write(flat) + + return base_dir + 'test.hda' diff --git a/src/web/file_cmds.py b/src/web/file_cmds.py new file mode 100644 index 00000000..415735a1 --- /dev/null +++ b/src/web/file_cmds.py @@ -0,0 +1,64 @@ +import fnmatch +import os +import subprocess +import time + +from ractl_cmds import attach_image +from settings import * +valid_file_types = ['*.hda', '*.iso', '*.cdr'] +valid_file_types = r'|'.join([fnmatch.translate(x) for x in valid_file_types]) + + +def create_new_image(file_name, type, size): + if file_name == "": + file_name = "new_image." + str(int(time.time())) + "." + type + else: + file_name = file_name + "." + type + + return subprocess.run(["dd", "if=/dev/zero", "of=" + base_dir + file_name, "bs=1M", "count=" + size], + capture_output=True) + + +def delete_image(file_name): + full_path = base_dir + file_name + if os.path.exists(full_path): + os.remove(full_path) + return True + else: + return False + + +def unzip_file(file_name): + import zipfile + with zipfile.ZipFile(base_dir + file_name, 'r') as zip_ref: + zip_ref.extractall(base_dir) + return True + +def rascsi_service(action): + # start/stop/restart + return subprocess.run(["sudo", "/bin/systemctl", action, "rascsi.service"]).returncode == 0 + + +def download_file_to_iso(scsi_id, url): + import urllib.request + file_name = url.split('/')[-1] + tmp_ts = int(time.time()) + tmp_dir = "/tmp/" + str(tmp_ts) + "/" + os.mkdir(tmp_dir) + tmp_full_path = tmp_dir + file_name + iso_filename = base_dir + file_name + ".iso" + + urllib.request.urlretrieve(url, tmp_full_path) + # iso_filename = make_cd(tmp_full_path, None, None) # not working yet + iso_proc = subprocess.run(["genisoimage", "-hfs", "-o", iso_filename, tmp_full_path], capture_output=True) + if iso_proc.returncode != 0: + return iso_proc + return attach_image(scsi_id, iso_filename, "cd") + + +def download_image(url): + import urllib.request + file_name = url.split('/')[-1] + full_path = base_dir + file_name + + urllib.request.urlretrieve(url, full_path) diff --git a/src/web/mock/bin/journalctl b/src/web/mock/bin/journalctl new file mode 100755 index 00000000..69e33536 --- /dev/null +++ b/src/web/mock/bin/journalctl @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +# Mock responses to rascsi-web +case $1 in + -n) + echo "logs $*" + ;; + + **) + echo "default" + ;; +esac diff --git a/src/web/mock/bin/rasctl b/src/web/mock/bin/rasctl new file mode 100755 index 00000000..c414d9b1 --- /dev/null +++ b/src/web/mock/bin/rasctl @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +# Mock responses to rascsi-web +case $1 in + -f) + echo "logs here" + ;; + + **) + echo "default" + ;; +esac diff --git a/src/web/mock/bin/systemctl b/src/web/mock/bin/systemctl new file mode 100755 index 00000000..9cdfa631 --- /dev/null +++ b/src/web/mock/bin/systemctl @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +# Mock responses to rascsi-web +case $1 in + is-active) + echo "is-active" + ;; + + **) + echo "default" + ;; +esac diff --git a/src/web/pi_cmds.py b/src/web/pi_cmds.py new file mode 100644 index 00000000..26f13086 --- /dev/null +++ b/src/web/pi_cmds.py @@ -0,0 +1,20 @@ +import subprocess + + +def rascsi_service(action): + # start/stop/restart + return subprocess.run(["sudo", "/bin/systemctl", action, "rascsi.service"]).returncode == 0 + + +def reboot_pi(): + return subprocess.run(["sudo", "reboot"]).returncode == 0 + + +def shutdown_pi(): + return subprocess.run(["sudo", "shutdown", "-h", "now"]).returncode == 0 + + +def running_version(): + ra_web_version = subprocess.run(["git", "rev-parse", "HEAD"], capture_output=True).stdout.decode("utf-8").strip() + pi_version = subprocess.run(["uname", "-a"], capture_output=True).stdout.decode("utf-8").strip() + return ra_web_version + " " + pi_version diff --git a/src/web/ractl_cmds.py b/src/web/ractl_cmds.py new file mode 100644 index 00000000..38614983 --- /dev/null +++ b/src/web/ractl_cmds.py @@ -0,0 +1,98 @@ +import fnmatch +import os +import subprocess +import re + +from settings import * +valid_file_types = ['*.hda', '*.iso', '*.cdr', '*.zip'] +valid_file_types = r'|'.join([fnmatch.translate(x) for x in valid_file_types]) +# List of SCSI ID's you'd like to exclude - eg if you are on a Mac, the System is usually 7 +EXCLUDE_SCSI_IDS = [7] + + +def is_active(): + process = subprocess.run(["systemctl", "is-active", "rascsi"], capture_output=True) + return process.stdout.decode("utf-8").strip() == "active" + + +def list_files(): + files_list = [] + for path, dirs, files in os.walk(base_dir): + # Only list valid file types + files = [f for f in files if re.match(valid_file_types, f)] + files_list.extend([ + (os.path.join(path, file), + # TODO: move formatting to template + '{:,.0f}'.format(os.path.getsize(os.path.join(path, file)) / float(1 << 20)) + " MB") + for file in files]) + return files_list + + +def get_valid_scsi_ids(devices): + invalid_list = EXCLUDE_SCSI_IDS.copy() + for device in devices: + if device['file'] != "NO MEDIA" and device['file'] != "-": + invalid_list.append(int(device['id'])) + + valid_list = list(range(8)) + for id in invalid_list: + valid_list.remove(id) + valid_list.reverse() + + return valid_list + + +def get_type(scsi_id): + return list_devices()[int(scsi_id)]["type"] + + +def attach_image(scsi_id, image, type): + if type == "cd" and get_type(scsi_id) == "SCCD": + return insert(scsi_id, image) + else: + return subprocess.run(["rasctl", "-c", "attach", "-t", type, "-i", scsi_id, "-f", image], capture_output=True) + + +def detach_by_id(scsi_id): + return subprocess.run(["rasctl", "-c" "detach", "-i", scsi_id], capture_output=True) + + +def disconnect_by_id(scsi_id): + return subprocess.run(["rasctl", "-c", "disconnect", "-i", scsi_id], capture_output=True) + + +def eject_by_id(scsi_id): + return subprocess.run(["rasctl", "-i", scsi_id, "-c", "eject"]) + + +def insert(scsi_id, image): + return subprocess.run(["rasctl", "-i", scsi_id, "-c", "insert", "-f", image], capture_output=True) + + +def rascsi_service(action): + # start/stop/restart + return subprocess.run(["sudo", "/bin/systemctl", action, "rascsi.service"]).returncode == 0 + + +def list_devices(): + device_list = [] + for id in range(8): + device_list.append({"id": str(id), "un": "-", "type": "-", "file": "-"}) + output = subprocess.run(["rasctl", "-l"], capture_output=True).stdout.decode("utf-8") + for line in output.splitlines(): + # Valid line to process, continue + if not line.startswith("+") and \ + not line.startswith("| ID |") and \ + (not line.startswith("No device is installed.") or line.startswith("No images currently attached.")) \ + and len(line) > 0: + line.rstrip() + device = {} + segments = line.split("|") + if len(segments) > 4: + idx = int(segments[1].strip()) + device_list[idx]["id"] = str(idx) + device_list[idx]['un'] = segments[2].strip() + device_list[idx]['type'] = segments[3].strip() + device_list[idx]['file'] = segments[4].strip() + + return device_list diff --git a/src/web/requirements.txt b/src/web/requirements.txt new file mode 100644 index 00000000..64d25bb4 --- /dev/null +++ b/src/web/requirements.txt @@ -0,0 +1,12 @@ +click==7.1.2 +Flask==1.1.2 +itsdangerous==1.1.0 +Jinja2==2.11.2 +machfs==1.2.4 +macresources==1.2 +MarkupSafe==1.1.1 +rsrcfork==1.8.0 +waitress==1.4.4 +Werkzeug==1.0.1 +zope.event==4.5.0 +zope.interface==5.1.2 diff --git a/src/web/service-infra/502.html b/src/web/service-infra/502.html new file mode 100644 index 00000000..f40d9ca8 --- /dev/null +++ b/src/web/service-infra/502.html @@ -0,0 +1,14 @@ + + + RaSCSI-web is Starting + + + + +
+

RaSCSI Web is starting....

+

This page will automatically refresh.

+

First boot and upgrades can take a second to resolve dependancies.

+

If you're seeing this page for over a minute please check the logs at sudo journalctl -f

+
+ \ No newline at end of file diff --git a/src/web/service-infra/nginx-default.conf b/src/web/service-infra/nginx-default.conf new file mode 100644 index 00000000..bffa96cc --- /dev/null +++ b/src/web/service-infra/nginx-default.conf @@ -0,0 +1,12 @@ +# /etc/nginx/sites-available/default +# Simple proxy_pass for RaSCSI-web +server { + location / { + proxy_pass http://localhost:8080; + } + + error_page 502 /502.html; + location = /502.html { + root /var/www/html/; + } +} \ No newline at end of file diff --git a/src/web/service-infra/rascsi-web.service b/src/web/service-infra/rascsi-web.service new file mode 100644 index 00000000..24d667a2 --- /dev/null +++ b/src/web/service-infra/rascsi-web.service @@ -0,0 +1,14 @@ +[Unit] +Description=RaSCSI-Web service +After=network.target + +[Service] +Type=simple +Restart=always +ExecStart=/home/pi/RASCSI/src/web/start.sh +StandardOutput=syslog +StandardError=syslog +SyslogIdentifier=RASCSIWEB + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/src/web/settings.py b/src/web/settings.py new file mode 100644 index 00000000..24acee41 --- /dev/null +++ b/src/web/settings.py @@ -0,0 +1,4 @@ +import os + +base_dir = os.getenv('BASE_DIR', "/home/pi/images/") +MAX_FILE_SIZE = os.getenv('MAX_FILE_SIZE', 1024 * 1024 * 1024 * 2) # 2gb diff --git a/src/web/start.sh b/src/web/start.sh new file mode 100755 index 00000000..ee0b1b37 --- /dev/null +++ b/src/web/start.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +set -e +# set -x # Uncomment to Debug + +cd $(dirname $0) +# verify packages installed +ERROR=0 +if ! command -v genisoimage &> /dev/null ; then + echo "genisoimage could not be found" + echo "Run 'sudo apt install genisoimage' to fix." + ERROR=1 +fi +if ! command -v python3 &> /dev/null ; then + echo "python3 could not be found" + echo "Run 'sudo apt install python3' to fix." + ERROR=1 +fi +if ! python3 -m venv --help &> /dev/null ; then + echo "venv could not be found" + echo "Run 'sudo apt install python3-venv' to fix." + ERROR=1 +fi +if ! command -v unzip &> /dev/null ; then + echo "unzip could not be found" + echo "Run 'sudo apt install unzip' to fix." + ERROR=1 +fi +if [ $ERROR = 1 ] ; then + echo + echo "Fix errors and re-run ./start.sh" + exit 1 +fi + +if ! test -e venv; then + echo "Creating python venv for web server" + python3 -m venv venv + echo "Activating venv" + source venv/bin/activate + echo "Installing requirements.txt" + pip install -r requirements.txt + git rev-parse HEAD > current +fi + +source venv/bin/activate + +# Detect if someone updates - we need to re-run pip install. +if ! test -e current; then + git rev-parse > current +else + if [ "$(cat current)" != "$(git rev-parse HEAD)" ]; then + echo "New version detected, updating requirements.txt" + pip install -r requirements.txt + git rev-parse HEAD > current + fi +fi + +echo "Starting web server..." +python3 web.py \ No newline at end of file diff --git a/src/php/rascsi_styles.css b/src/web/static/style.css similarity index 68% rename from src/php/rascsi_styles.css rename to src/web/static/style.css index c98b6044..9d5dd136 100644 --- a/src/php/rascsi_styles.css +++ b/src/web/static/style.css @@ -21,8 +21,24 @@ a { text-decoration: none; } +form { + display: inline; +} + table, tr, td { border: 1px solid black; border-collapse:collapse; margin: none; } + +.error { + color: white; + font-size:20px; + background-color:red; +} + +.message { + color: white; + font-size:20px; + background-color:green; +} \ No newline at end of file diff --git a/src/web/templates/base.html b/src/web/templates/base.html new file mode 100644 index 00000000..ddc9dc40 --- /dev/null +++ b/src/web/templates/base.html @@ -0,0 +1,24 @@ + +RaSCSI Control Page + + +
+
+ {% block header %}{% endblock %} +
+
+ {% for category, message in get_flashed_messages(with_categories=true) %} + {% if category == "stdout" or category == "stderr" %} +
{{message}}
+ {% else %} +
{{ message }}
+ {% endif %} + {% endfor %} +
+
+ {% block content %}{% endblock %} +
+ +
\ No newline at end of file diff --git a/src/web/templates/index.html b/src/web/templates/index.html new file mode 100644 index 00000000..a11fab57 --- /dev/null +++ b/src/web/templates/index.html @@ -0,0 +1,213 @@ +{% extends "base.html" %} + +{% block header %} +{% if active %} +Service Running +{% else %} +Service Stopped +{% endif %} + + + + + + +
+ +

RaSCSI - 68kmla Edition

+
+
+ {% endblock %} + + {% block content %} +

Current RaSCSI Configuration

+ + + + + + + + + {% for device in devices %} + + {% if device.id != "7" %} + + + + + {% else %} + + + + + {% endif %} + + {% endfor %} + +
IDTypeFileAction
{{device.id}}{{device.type}}{{device.file}} + {% if device.type == "SCCD" and device.file != "NO MEDIA" %} + + + + + {% else %} +
+ + +
+ {% endif %} +
{{device.id}}-Host Machine-
+ +

Image File Management

+ + + + + + + + {% for file in files %} + + + + + + {% endfor %} + +
FileSizeActions
{{file[0].replace(base_dir, '')}} +
+ + +
+
+
+ + + +
+
+ + +
+ {% if file[0].endswith('.zip') or file[0].endswith('.ZIP') %} +
+ + +
+ {% endif %} +
+ +
+ +

Upload File

+

Uploads file to {{base_dir}}. Max file size is set to {{max_file_size / 1024 /1024 }}MB

+ + + + +
+
+ + + +
+
+ +
+ +

Download File from Web

+

Given a URL, download that file to the {{base_dir}}

+ + + + +
+
+ + + +
+
+ +
+ +

Download File from web and create HFS CD

+

Given a URL this will download a file, create a HFS iso, and mount it on the device id given.

+ + + + +
+ +
+ + + + +
+
+ +
+

Create Empty Disk Image File

+ + + + +
+
+ + + + + + + +
+
+ +
+ +

Raspberry Pi Operations

+ + + + + + + +
+
+ +
+
+
+ +
+
+
+ +
+
+{% endblock %} + +{% block footer %} +
{{version}}
+
Logs
+{% endblock %} \ No newline at end of file diff --git a/src/web/web.py b/src/web/web.py new file mode 100644 index 00000000..f2965a7a --- /dev/null +++ b/src/web/web.py @@ -0,0 +1,206 @@ +import os + +from flask import Flask, render_template, request, flash, url_for, redirect, send_file +from werkzeug.utils import secure_filename + +from file_cmds import create_new_image, download_file_to_iso, delete_image, unzip_file, download_image +from pi_cmds import shutdown_pi, reboot_pi, running_version, rascsi_service +from ractl_cmds import attach_image, list_devices, is_active, list_files, detach_by_id, eject_by_id, get_valid_scsi_ids +from settings import * + +app = Flask(__name__) + +@app.route('/') +def index(): + devices = list_devices() + scsi_ids = get_valid_scsi_ids(devices) + return render_template('index.html', + devices=devices, + active=is_active(), + files=list_files(), + base_dir=base_dir, + scsi_ids=scsi_ids, + max_file_size=MAX_FILE_SIZE, + version=running_version()) + +@app.route('/logs') +def logs(): + import subprocess + lines = request.args.get('lines') or "100" + process = subprocess.run(["journalctl", "-n", lines], capture_output=True) + + if process.returncode == 0: + headers = { 'content-type':'text/plain' } + return process.stdout.decode("utf-8"), 200, headers + else: + flash(u'Failed to get logs') + flash(process.stdout.decode("utf-8"), 'stdout') + flash(process.stderr.decode("utf-8"), 'stderr') + return redirect(url_for('index')) + + +@app.route('/scsi/attach', methods=['POST']) +def attach(): + file_name = request.form.get('file_name') + scsi_id = request.form.get('scsi_id') + + # Validate image type by suffix + if file_name.lower().endswith('.iso') or file_name.lower().endswith('iso'): + image_type = "cd" + elif file_name.lower().endswith('.hda'): + image_type = "hd" + else: + flash(u'Unknown file type. Valid files are .iso, .hda, .cdr', 'error') + return redirect(url_for('index')) + + process = attach_image(scsi_id, file_name, image_type) + if process.returncode == 0: + flash('Attached '+ file_name + " to scsi id " + scsi_id + "!") + return redirect(url_for('index')) + else: + flash(u'Failed to attach '+ file_name + " to scsi id " + scsi_id + "!", 'error') + flash(process.stdout.decode("utf-8"), 'stdout') + flash(process.stderr.decode("utf-8"), 'stderr') + return redirect(url_for('index')) + + +@app.route('/scsi/detach', methods=['POST']) +def detach(): + scsi_id = request.form.get('scsi_id') + process = detach_by_id(scsi_id) + if process.returncode == 0: + flash("Detached scsi id " + scsi_id + "!") + return redirect(url_for('index')) + else: + flash(u"Failed to detach scsi id " + scsi_id + "!", 'error') + flash(process.stdout, 'stdout') + flash(process.stderr, 'stderr') + return redirect(url_for('index')) + + +@app.route('/scsi/eject', methods=['POST']) +def eject(): + scsi_id = request.form.get('scsi_id') + process = eject_by_id(scsi_id) + if process.returncode == 0: + flash("Ejected scsi id " + scsi_id + "!") + return redirect(url_for('index')) + else: + flash(u"Failed to eject scsi id " + scsi_id + "!", 'error') + flash(process.stdout, 'stdout') + flash(process.stderr, 'stderr') + return redirect(url_for('index')) + + +@app.route('/pi/reboot', methods=['POST']) +def restart(): + reboot_pi() + flash("Restarting...") + return redirect(url_for('index')) + + +@app.route('/rascsi/restart', methods=['POST']) +def rascsi_restart(): + rascsi_service("restart") + flash("Restarting RaSCSI Service...") + return redirect(url_for('index')) + + +@app.route('/pi/shutdown', methods=['POST']) +def shutdown(): + shutdown_pi() + flash("Shutting down...") + return redirect(url_for('index')) + + +@app.route('/files/download_to_iso', methods=['POST']) +def download_file(): + scsi_id = request.form.get('scsi_id') + url = request.form.get('url') + process = download_file_to_iso(scsi_id, url) + if process.returncode == 0: + flash("File Downloaded") + return redirect(url_for('index')) + else: + flash(u"Failed to download file", 'error') + flash(process.stdout, 'stdout') + flash(process.stderr, 'stderr') + return redirect(url_for('index')) + + +@app.route('/files/download_image', methods=['POST']) +def download_img(): + url = request.form.get('url') + # TODO: error handling + download_image(url) + flash("File Downloaded") + return redirect(url_for('index')) + + +@app.route('/files/upload', methods=['POST']) +def upload_file(): + if 'file' not in request.files: + flash('No file part', 'error') + return redirect(url_for('index')) + file = request.files['file'] + if file: + filename = secure_filename(file.filename) + file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) + return redirect(url_for('index', filename=filename)) + + +@app.route('/files/create', methods=['POST']) +def create_file(): + file_name = request.form.get('file_name') + size = request.form.get('size') + type = request.form.get('type') + + process = create_new_image(file_name, type, size) + if process.returncode == 0: + flash("Drive created") + return redirect(url_for('index')) + else: + flash(u"Failed to create file", 'error') + flash(process.stdout, 'stdout') + flash(process.stderr, 'stderr') + return redirect(url_for('index')) + + +@app.route('/files/download', methods=['POST']) +def download(): + image = request.form.get('image') + return send_file(base_dir + image, as_attachment=True) + + +@app.route('/files/delete', methods=['POST']) +def delete(): + image = request.form.get('image') + if delete_image(image): + flash("File " + image + " deleted") + return redirect(url_for('index')) + else: + flash(u"Failed to Delete " + image, 'error') + return redirect(url_for('index')) + + +@app.route('/files/unzip', methods=['POST']) +def unzip(): + image = request.form.get('image') + + if unzip_file(image): + flash("Unzipped file " + image) + return redirect(url_for('index')) + else: + flash(u"Failed to unzip " + image, 'error') + return redirect(url_for('index')) + + +if __name__ == "__main__": + app.secret_key = 'rascsi_is_awesome_insecure_secret_key' + app.config['SESSION_TYPE'] = 'filesystem' + app.config['UPLOAD_FOLDER'] = base_dir + os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True) + app.config['MAX_CONTENT_LENGTH'] = MAX_FILE_SIZE + + from waitress import serve + serve(app, host="0.0.0.0", port=8080)