diff --git a/roles/nginx/templates/iiab.conf.j2 b/roles/nginx/templates/iiab.conf.j2 index df2fc6a94..e3fdee774 100644 --- a/roles/nginx/templates/iiab.conf.j2 +++ b/roles/nginx/templates/iiab.conf.j2 @@ -5,10 +5,25 @@ location / { location /usb { alias /library/www/html/local_content/; fancyindex on; # autoindex on; + add_before_body /usb/upload/button.html; +} + +location ~ ^/usb/upload/(.*)\.php$ { + alias /library/www/html/local_content/upload/$1.php; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header Host $host; + fastcgi_pass php; + fastcgi_index index.php; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param SCRIPT_NAME $fastcgi_script_name; + include fastcgi_params; } location /local_content/ { fancyindex on; # autoindex on; + add_before_body /usb/upload/button.html; } location /info { diff --git a/roles/usb_lib/files/upload/button.html b/roles/usb_lib/files/upload/button.html new file mode 100644 index 000000000..658f74fb2 --- /dev/null +++ b/roles/usb_lib/files/upload/button.html @@ -0,0 +1,19 @@ + +Upload to USB diff --git a/roles/usb_lib/files/upload/error.php b/roles/usb_lib/files/upload/error.php new file mode 100644 index 000000000..c5210d229 --- /dev/null +++ b/roles/usb_lib/files/upload/error.php @@ -0,0 +1,16 @@ + + +ERROR: Please make sure one and ONLY one (no more, no less) removable USB stick is plugged into your Internet-in-a-Box. Please see IIAB FAQs for additional support: FAQ #4 - Can teachers display their own content?, FAQ #49 - What are the best places for community support?. + +

+ +
+ + + diff --git a/roles/usb_lib/files/upload/footer.php b/roles/usb_lib/files/upload/footer.php new file mode 100644 index 000000000..2e1fef0f7 --- /dev/null +++ b/roles/usb_lib/files/upload/footer.php @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/roles/usb_lib/files/upload/header.php b/roles/usb_lib/files/upload/header.php new file mode 100644 index 000000000..78592e86d --- /dev/null +++ b/roles/usb_lib/files/upload/header.php @@ -0,0 +1,32 @@ + + + + + + + <?php echo $title ?> + + + + + + + + + + +
+
+
+ + +

diff --git a/roles/usb_lib/files/upload/index.php b/roles/usb_lib/files/upload/index.php new file mode 100644 index 000000000..6eab98dbf --- /dev/null +++ b/roles/usb_lib/files/upload/index.php @@ -0,0 +1,24 @@ + + +
+
+

+ +
+
+ files have been uploaded today! + + + \ No newline at end of file diff --git a/roles/usb_lib/files/upload/uk-swing.png b/roles/usb_lib/files/upload/uk-swing.png new file mode 100644 index 000000000..c5470365e Binary files /dev/null and b/roles/usb_lib/files/upload/uk-swing.png differ diff --git a/roles/usb_lib/files/upload/upload-file.php b/roles/usb_lib/files/upload/upload-file.php new file mode 100644 index 000000000..a3c6e9674 --- /dev/null +++ b/roles/usb_lib/files/upload/upload-file.php @@ -0,0 +1,57 @@ +". htmlspecialchars( $uploaded_filename ). " was successfully uploaded!"; + } else { + $upload_msg = "❌ There was an error uploading your file. " . $_FILES["upload_file"]["error"] . $upload_msg; + } +} + +$file_count = getFileCount($target_folder_path); + +?> + +
+ files have been uploaded today! + + + + diff --git a/roles/usb_lib/files/upload/upload2usb.php b/roles/usb_lib/files/upload/upload2usb.php new file mode 100644 index 000000000..f2b3aa883 --- /dev/null +++ b/roles/usb_lib/files/upload/upload2usb.php @@ -0,0 +1,104 @@ +usb sticks are installed + $rmv_usb_path_count = shell_exec('lsblk --output NAME,TRAN,RM,MOUNTPOINT --pairs |grep RM=\"1\" | grep -v MOUNTPOINT=\"\" | cut -d " " -f 4 | wc -l'); + if ($rmv_usb_path_count == 0) { + throw new RuntimeException('0 USB sticks found.

'); + } elseif ($rmv_usb_path_count > 1) { + throw new RuntimeException('More than 1 USB sticks installed.

'); + } + + $rmv_usb_path = trim(str_replace('"', '', shell_exec('lsblk --output NAME,TRAN,RM,MOUNTPOINT --pairs |grep RM=\"1\" | grep -v MOUNTPOINT=\"\" | cut -d " " -f 4 | cut -d "=" -f 2'))); + + if (empty($rmv_usb_path)) { + throw new RuntimeException('Not able to find USB stick.

'); + } else { + return $rmv_usb_path . "/"; + } +} + +//returns folder path where file will be stored, if create_folder_p = 1, it will create the folder if it doesn't exist +function getTargetFolderPath ($create_folder_p) { + $parent_dir = getTargetUSBDriveLocation(); + + $today_folder_name = "UPLOADS." . date("Y-m-d"); + $target_folder_path = $parent_dir . $today_folder_name; + + if (!file_exists($target_folder_path) && $create_folder_p) { + mkdir($target_folder_path, 0777) or throw new RuntimeException("Not able to create upload directory.
Make sure 'usb_lib_umask0000_for_kolibri' is set to 'True'.

"); + } + return $target_folder_path; +} + +//return number of files within a specified folder +function getFileCount ($folder_path) { + return count(glob($folder_path . "/*")); +} + +//check if file mimetype is acceptable for upload +function isFileMimeTypeAcceptable ($file) { + $mimetype = strtolower(mime_content_type($file)); + $invalid_mimetypes_str = array ("compress", "image/svg+xml", "octet", "text/xml", "xhtml+xml", "zip"); + foreach ($invalid_mimetypes_str as $invalid_mt_str) { + if (str_contains($mimetype, $invalid_mt_str)) { + error_log('UPLOAD2USB ERROR - MIMETYPE: ' . $mimetype); + return false; + } + } + return true; +} + +//check file content to see if it's unique or not +function isFileContentUnique ($target_folder_path, $file) { + $file_to_upload_md5 = md5_file($file); + $usb_dir = array_diff(scandir($target_folder_path), array('..', '.')); + foreach ($usb_dir as $dir_file) { + $dir_file = $target_folder_path . "/" . $dir_file; + + if (!is_dir($dir_file)) { + $dir_file_md5 = md5_file($dir_file); + if ($file_to_upload_md5 == $dir_file_md5) { + return false; + } + } + } + return true; +} + +//return unique filename +function getUniqueFileName ($target_folder_path, $filename) { + $new_filename = $filename; + $counter = 1; + while (file_exists($target_folder_path . "/" . $new_filename)) { + $counter++; + $new_filename = pathinfo($filename,8) . '-'. $counter . "." . pathinfo($filename,4); + } + return $new_filename; +} + +// Check file size - we are not going to check file size for now. +// elseif ($_FILES["uploaded_file"]["size"] > 5000000) { +// $upload_msg = "Your file is too large."; +// $upload_ok = 0; +// } + + + +?> diff --git a/roles/usb_lib/tasks/install.yml b/roles/usb_lib/tasks/install.yml index e0699a652..e435719dc 100644 --- a/roles/usb_lib/tasks/install.yml +++ b/roles/usb_lib/tasks/install.yml @@ -7,6 +7,9 @@ # https://github.com/rbrito/usbmount/blob/master/README.md (2018-08-10) # https://github.com/rbrito/usbmount/blob/master/usbmount.conf (2010-04-25) +# usb_lib_umask0000_for_kolibri (e.g., in /etc/iiab/local_vars.yml) must be set to true in order to be able to write to mounted USB sticks +# If you are still not able to write to a mounted USB stick, you can unmount the drive (sudo umount ) and then remount it setting umask to 0000 manually (sudo mount -o umask=0000 ). + - name: Record (initial) disk space used shell: df -B1 --output=used / | tail -1 @@ -76,6 +79,21 @@ - { src: 'iiab-usb_lib-show-all-off', dest: '/usr/bin/', mode: '0755' } - { src: 'iiab-clean-usb.sh', dest: '/usr/sbin/', mode: '0755' } +- name: '2025-01-05: Add upload2usb app (#3875) directory to local_content' + file: + state: directory + path: "{{ doc_root }}/local_content/upload" + owner: "{{ apache_user }}" + group: "{{ apache_user }}" + mode: 0755 + +- name: '2025-01-05: Copy upload2usb app (#3875) files from files/upload/ to local_content' + copy: + src: "{{ item }}" + dest: "{{ doc_root }}/local_content/upload" # /library/www/html + with_fileglob: + - upload/* + # 2021-03-21: If usbmount is repackaged by apt as a result of Linux kernel 5.4+ # supporting exFAT, the stanza below (might) in future no longer be needed... # SEE ALSO: https://github.com/iiab/iiab/blob/586bfc5cb1abf6b4333a21d3fa89695f115432dc/roles/2-common/tasks/packages.yml#L11-L12