Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat big gui update #16

Closed
wants to merge 32 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
330aaff
Fix file indexing in web ui
philippderdiedas Feb 19, 2024
bfad1cd
remove . and .. from list.php
philippderdiedas Feb 19, 2024
f41a7eb
fix file indexing in web ui
philippderdiedas Feb 19, 2024
d5327cf
rework ui
philippderdiedas Feb 19, 2024
c42ee64
rework
philippderdiedas Feb 20, 2024
42fb87b
fix username in brscan-skey
philippderdiedas Feb 20, 2024
00fe778
merge
philippderdiedas Feb 21, 2024
3b28c8a
fix php typos
philippderdiedas Feb 24, 2024
af3d046
Merge branch 'PhilippMundhenk:master' into pull-request
philippderdiedas Feb 24, 2024
a986541
Merge pull request #15 from philippderdiedas/pull-request
PhilippMundhenk Feb 25, 2024
fd4ffbb
fixing variable handling (=false used to return true)
PhilippMundhenk Feb 25, 2024
f077c65
adding backwards compatbility for webserver settings
PhilippMundhenk Feb 25, 2024
3c44884
added note of deprecation in README
PhilippMundhenk Feb 25, 2024
d39ed6b
fixing typos
PhilippMundhenk Feb 25, 2024
88c289c
added required ports again
PhilippMundhenk Feb 25, 2024
3f98ee3
account for ping being disabled
PhilippMundhenk Feb 25, 2024
8a0e23b
make ping interval configurable
PhilippMundhenk Feb 25, 2024
3f6b46c
added status hint to website
PhilippMundhenk Feb 25, 2024
08e2a21
fixed missing bracket
PhilippMundhenk Feb 25, 2024
1a16492
added more backwards compatibility
PhilippMundhenk Feb 25, 2024
5e31128
added more notes on deprecated variables
PhilippMundhenk Feb 25, 2024
9198ff3
debugging download
PhilippMundhenk Feb 25, 2024
9389f45
fixed typos
PhilippMundhenk Feb 25, 2024
33f8e5a
fixed file path
PhilippMundhenk Feb 25, 2024
465a889
saving webserver ping status
PhilippMundhenk Feb 25, 2024
37558fc
trying to get status in another way
PhilippMundhenk Feb 25, 2024
57c5989
removed hint to filename
PhilippMundhenk Feb 25, 2024
68f074e
added proper comparison
PhilippMundhenk Feb 25, 2024
38f02d9
handled backward compatibility better
PhilippMundhenk Feb 25, 2024
1129af5
more backward compatibility fixes
PhilippMundhenk Feb 25, 2024
c945b68
missing semicolon
PhilippMundhenk Feb 25, 2024
d1ee52f
fix ui lock on unknown state
philippderdiedas Feb 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 39 additions & 30 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,49 +1,63 @@
#FROM ubuntu:16.04
FROM ubuntu:22.04
FROM debian:bookworm-slim AS builder

RUN DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get update && apt-get -y install tzdata && apt-get -y clean
ARG DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y --no-install-recommends apt-utils && apt-get -y clean
RUN apt-get update && apt-get -y --no-install-recommends install \
wget \
ca-certificates

RUN cd /tmp && \
wget https://download.brother.com/welcome/dlf105200/brscan4-0.4.11-1.amd64.deb

RUN cd /tmp && \
wget https://download.brother.com/welcome/dlf006652/brscan-skey-0.3.1-2.amd64.deb

FROM debian:bookworm-slim

RUN apt-get -y update && apt-get -y upgrade && apt-get -y clean
RUN apt-get -y install \
ARG DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get -y --no-install-recommends install \
sane \
sane-utils \
netbase \
ghostscript \
netpbm \
x11-common \
wget \
graphicsmagick \
curl \
ssh \
sshpass \
lighttpd \
php-cgi \
php-curl \
sudo \
iproute2 \
iputils-ping \
&& apt-get -y clean

COPY --from=builder /tmp/brscan4-0.4.11-1.amd64.deb /tmp/brscan4-0.4.11-1.amd64.deb
RUN cd /tmp && \
wget https://download.brother.com/welcome/dlf105200/brscan4-0.4.11-1.amd64.deb && \
dpkg -i /tmp/brscan4-0.4.11-1.amd64.deb && \
rm /tmp/brscan4-0.4.11-1.amd64.deb

COPY --from=builder /tmp/brscan-skey-0.3.1-2.amd64.deb /tmp/brscan-skey-0.3.1-2.amd64.deb
RUN cd /tmp && \
wget https://download.brother.com/welcome/dlf006652/brscan-skey-0.3.1-2.amd64.deb && \
dpkg -i /tmp/brscan-skey-0.3.1-2.amd64.deb && \
rm /tmp/brscan-skey-0.3.1-2.amd64.deb

ADD files/runScanner.sh /opt/brother/runScanner.sh
COPY script /opt/brother/scanner/brscan-skey/script
RUN lighty-enable-mod auth || true; \
lighty-enable-mod fastcgi || true; \
lighty-enable-mod fastcgi-php || true; \
lighty-enable-mod access || true

RUN cat <<EOF >> /etc/lighttpd/lighttpd.conf
\$HTTP["url"] =~ "^/lib" {
url.access-deny = ("")
}
EOF

RUN cp /etc/lighttpd/conf-available/05-auth.conf /etc/lighttpd/conf-enabled/
RUN cp /etc/lighttpd/conf-available/15-fastcgi-php.conf /etc/lighttpd/conf-enabled/
RUN cp /etc/lighttpd/conf-available/10-fastcgi.conf /etc/lighttpd/conf-enabled/
RUN mkdir -p /var/run/lighttpd
RUN touch /var/run/lighttpd/php-fastcgi.socket
RUN chown -R www-data /var/run/lighttpd
RUN echo 'www-data ALL=(NAS) NOPASSWD:ALL' >> /etc/sudoers

ENV TZ=Etc/UTC

ENV NAME="Scanner"
ENV MODEL="MFC-L2700DW"
Expand All @@ -63,21 +77,16 @@ ENV FTP_HOST=""
# Make sure this ends in a slash.
ENV FTP_PATH="/scans/"

EXPOSE 54925
EXPOSE 54921
EXPOSE 80

ADD files/gui/index.php /var/www/html
ADD files/gui/main.css /var/www/html
ADD files/api/scan.php /var/www/html
ADD files/api/active.php /var/www/html
ADD files/api/list.php /var/www/html
ADD files/api/download.php /var/www/html
COPY files/gui/ /var/www/html
COPY files/api/ /var/www/html

COPY files/runScanner.sh /opt/brother/runScanner.sh
COPY script /opt/brother/scanner/brscan-skey/script

RUN chown -R www-data /var/www/

#directory for scans:
VOLUME /scans

CMD /opt/brother/runScanner.sh


CMD /opt/brother/runScanner.sh
61 changes: 35 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ You can configure the tool via environment variables:

| Variable | Type | Description |
| ------------- | ------------- | ------------- |
| NAME | mandatory | Arbitrary name to give your scanner. Displayed on scanner, if multiple servers are running. |
| NAME | mandatory | Arbitrary name to give your scanner. |
| USERNAME | optional | Displayed on scanner, if multiple servers are running. |
| MODEL | mandatory | Model of your scanner (e.g., MFC-L2700DW) |
| IPADDRESS | mandatory | IP Address of your scanner |
| RESOLUTION | optional | DPI resolution of scan, refer to capabilities of printer on startup |
Expand All @@ -101,17 +102,25 @@ You can configure the tool via environment variables:
| OCR_SERVER | optional | Hostname of an OCR server (see below) |
| OCR_PORT | optional | Port of an OCR server (see below) |
| OCR_PATH | optional | Path of an OCR server (see below) |
| WEBSERVER | optional | activates GUI & API (default:false) (see below) |
| PORT | optional | sets port for webserver (default: 80) |
| DISABLE_GUI_SCANTOFILE | optional | deactivates button "Scan to file" (default: false) |
| DISABLE_GUI_SCANTOEMAIL | optional | deactivates button "Scan to e-mail" |
| DISABLE_GUI_SCANTOIMAGE | optional | deactivates button "Scan to image" |
| DISABLE_GUI_SCANTOOCR | optional | deactivates button "Scan to OCR" |
| RENAME_GUI_SCANTOFILE="Scan front pages" | optional | renames GUI button "Scan to file" to "Scan front pages" |
| RENAME_GUI_SCANTOEMAIL="Scan rear pages" | optional | renames GUI button "Scan to email" to "Scan rear pages" |
| RENAME_GUI_SCANTOIMAGE="Scan photo" | optional | renames GUI button "Scan to image" to "Scan photo" |
| RENAME_GUI_SCANTOOCR="Scan High-Res" | optional | renames GUI button "Scan to OCR" to "Scan High-Res" |
| WEBSERVER_ENABLE | optional | activates GUI & API (default:true) (see below) |
| WEBSERVER_PING_ENABLE | optional | activates ping service to check if scanner offline |
| WEBSERVER_PING_INTERVAL | optional | sets interval how often to ping the scanner |
| WEBSERVER_PORT | optional | sets port for webserver (default: 80) |
| WEBSERVER_LABEL_SCANTOFILE | optional | empty to hide button (default: "Scan to file") |
| WEBSERVER_LABEL_SCANTOEMAIL | optional | empty to hide button (default: "Scan to email") |
| WEBSERVER_LABEL_SCANTOIMAGE | optional | empty to hide button (default: "Scan to image") |
| WEBSERVER_LABEL_SCANTOOCR | optional | empty to hide button (default: "Scan to OCR") |
| USE_JPEG_COMPRESSION | optional | use JPEG compression when creating PDFs |
| ~~WEBSERVER~~ | deprecated | replaced by WEBSERVER_ENABLE |
| ~~PORT~~ | deprecated | replaced by WEBSERVER_PORT |
| ~~DISABLE_GUI_SCANTOFILE~~ | deprecated | use WEBSERVER_LABEL_SCANTOFILE instead |
| ~~DISABLE_GUI_SCANTOEMAIL~~ | deprecated | use WEBSERVER_LABEL_SCANTOEMAIL instead |
| ~~DISABLE_GUI_SCANTOIMAGE~~ | deprecated | use WEBSERVER_LABEL_SCANTOIMAGE instead |
| ~~DISABLE_GUI_SCANTOOCR~~ | deprecated | use WEBSERVER_LABEL_SCANTOOCR instead |
| ~~RENAME_GUI_SCANTOFILE="Scan front pages"~~ | deprecated | use WEBSERVER_LABEL_SCANTOFILE instead |
| ~~RENAME_GUI_SCANTOEMAIL="Scan rear pages"~~ | deprecated | use WEBSERVER_LABEL_SCANTOEMAIL instead |
| ~~RENAME_GUI_SCANTOIMAGE="Scan photo"~~ | deprecated | use WEBSERVER_LABEL_SCANTOIMAGE instead |
| ~~RENAME_GUI_SCANTOOCR="Scan High-Res"~~ | deprecated | use WEBSERVER_LABEL_SCANTOOCR instead |

### FTPS upload
In addition to the storage in the mounted volume, you can use FTPS (Secure FTP) Upload.
Expand Down Expand Up @@ -161,12 +170,13 @@ By default, the image uses port 80, but you may configure that.
Additionally, for the GUI, you can rename and hide individual functions.
here is an example of the environment:
```
- WEBSERVER=true # optional, activates GUI & API
- PORT=33355 # optional, sets port for webserver (default: 80)
- DISABLE_GUI_SCANTOIMAGE=true # optional, deactivates button "Scan to image"
- DISABLE_GUI_SCANTOOCR=true # optional, deactivates button "Scan to OCR"
- RENAME_GUI_SCANTOFILE="Scan front pages" # optional, renames button "Scan to file" to "Scan front pages"
- RENAME_GUI_SCANTOEMAIL="Scan rear pages" # optional, renames button "Scan to email" to "Scan rear pages"
- WEBSERVER_ENABLE= # optional, activates GUI & API
- WEBSERVER_PING_ENABLE= # optional, if enabled scanner status is `online`, `offline`, `scanning` (see status.php)
- WEBSERVER_PORT=33355 # optional, sets port for webserver (default: 80)
- WEBSERVER_LABEL_SCANTOIMAGE= # optional, hides button "Scan to image"
- WEBSERVER_LABEL_SCANTOOCR= # optional, hides button "Scan to OCR"
- WEBSERVER_LABEL_SCANTOFILE="Scan front pages" # optional, renames button "Scan to file" to "Scan front pages"
- WEBSERVER_LABEL_SCANTOEMAIL="Scan rear pages" # optional, renames button "Scan to email" to "Scan rear pages"
```

#### GUI
Expand All @@ -180,7 +190,7 @@ Thus, make sure to wait for your scan to complete, before pressing another butto
#### API
The GUI uses a minimal "API" at the backend, which you can also use from other tooling (e.g., Home Assistant or a control panel near your printer).
To scan, simply call `http://<ContainerIP>:<Port>/scan.php?target=<file|email|image|OCR>`
Also check out the endpoints `list.php`, `download.php`, `active.php`.
Also check out the endpoints `list.php`, `listfiles.php`, `download.php`, `active.php` and `status.php`.
Maybe one day an OpenAPI Spec will be included.

## Full Docker Compose Example
Expand All @@ -195,10 +205,8 @@ services:
volumes:
- /path/on/host:/scans
ports:
- 33355:33355
- 33355:33355 # example webserver port
- 54925:54925/udp # mandatory, for scanner tools
- 54921:54921 # mandatory, for scanner tools
- 161:161/udp # mandatory, for scanner tools
environment:
- NAME=Scanner
- MODEL=MFC-L2700DW
Expand All @@ -210,12 +218,13 @@ services:
- UID=1000 # optional, for /scans permissions
- GID=1000 # optional, for /scans permissions
- TZ=Europe/Berlin # optional, for correct time in scanned filenames
- WEBSERVER=true # optional, activates GUI & API
- WEBSERVER_ENABLE= # optional, activates GUI & API
- WEBSERVER_PING_ENABLE= # optional, activates ping service to check if scanner offline
- PORT=33355 # optional, sets port for webserver (default: 80)
- DISABLE_GUI_SCANTOIMAGE=true # optional, deactivates button "Scan to image"
- DISABLE_GUI_SCANTOOCR=true # optional, deactivates button "Scan to OCR"
- RENAME_GUI_SCANTOFILE="Scan front pages" # optional, renames button "Scan to file" to "Scan front pages"
- RENAME_GUI_SCANTOEMAIL="Scan rear pages" # optional, renames button "Scan to email" to "Scan rear pages"
- WEBSERVER_LABEL_SCANTOIMAGE= # optional, deactivates button "Scan to image"
- WEBSERVER_LABEL_SCANTOOCR=true # optional, deactivates button "Scan to OCR"
- WEBSERVER_LABEL_SCANTOFILE="Scan front pages" # optional, renames button "Scan to file" to "Scan front pages"
- WEBSERVER_LABEL_SCANTOEMAIL="Scan rear pages" # optional, renames button "Scan to email" to "Scan rear pages"
restart: unless-stopped

# optional, for OCR
Expand Down
26 changes: 14 additions & 12 deletions files/api/download.php
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
<?php
include_once(__DIR__."/lib/lib.php");

if ($_SERVER['REQUEST_METHOD'] == 'GET') {

if(array_key_exists("file", $_GET)) {
$file = $_GET["file"];
if(str_contains($file, "..") || str_contains($file, "/")) {
header($_SERVER["SERVER_PROTOCOL"] . " 400 OK");
die("Error: Dont't be evil!");
}
$filename="/scans/".$file;
if(file_exists($filename)) {
header("Content-type:application/pdf");
header("Content-Disposition:attachment;filename=\"scan.pdf\"");
readfile($filename);
$filename = $_GET["file"];
$filepath=$SCANS_DIR . '/' . $filename;
if(file_exists($filepath) && is_sub_path($filepath, $SCANS_DIR)) {
header("Content-type: " . (mime_content_type($filepath) || 'application/octet-stream'));
header("Content-Disposition: attachment; filename=\"" . $filename . "\"");
readfile($filepath);
} else {
header($_SERVER["SERVER_PROTOCOL"] . " 400 OK");
http_response_code(404);
die("Error: File does not exist!");
}
} else {
header($_SERVER["SERVER_PROTOCOL"] . " 400 OK");
http_response_code(400);
die("Error: No file provided!");
}
} else {
http_response_code(405);
die("Error: Method not allowed!");
}
?>
8 changes: 8 additions & 0 deletions files/api/lib/lib.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php
include_once(__DIR__."/listfiles.php");
include_once(__DIR__."/subdircheck.php");

// constants
$SCANS_DIR = "/scans";
$SCRIPTS_DIR = "/opt/brother/scanner/brscan-skey/script";
?>
68 changes: 68 additions & 0 deletions files/api/lib/listfiles.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

// Define constants for sorting flags
define('GETFILELIST_SORT_NAME_ASC', 1);
define('GETFILELIST_SORT_NAME_DESC', 2);
define('GETFILELIST_SORT_CREATEDATE_ASC', 4);
define('GETFILELIST_SORT_CREATEDATE_DESC', 8);
define('GETFILELIST_SORT_MODIFYDATE_ASC', 16);
define('GETFILELIST_SORT_MODIFYDATE_DESC', 32);
define('GETFILELIST_SORT_DIRNAME_ASC', 64);
define('GETFILELIST_SORT_DIRNAME_DESC', 128);

function getFileList($path, $sortFlags = GETFILELIST_SORT_NAME_ASC) {
// Check if the directory exists
if (!is_dir($path)) {
return [];
}

$files = [];

// Helper function to sort by various criteria
$sortFunction = function ($a, $b) use ($sortFlags) {
if ($sortFlags & GETFILELIST_SORT_NAME_ASC || $sortFlags & GETFILELIST_SORT_NAME_DESC) {
return strnatcasecmp($a, $b);
} elseif ($sortFlags & GETFILELIST_SORT_CREATEDATE_ASC) {
return filectime($a) - filectime($b);
} elseif ($sortFlags & GETFILELIST_SORT_CREATEDATE_DESC) {
return filectime($b) - filectime($a);
} elseif ($sortFlags & GETFILELIST_SORT_MODIFYDATE_ASC) {
return filemtime($a) - filemtime($b);
} elseif ($sortFlags & GETFILELIST_SORT_MODIFYDATE_DESC) {
return filemtime($b) - filemtime($a);
} elseif ($sortFlags & GETFILELIST_SORT_DIRNAME_ASC) {
return strnatcasecmp(dirname($a), dirname($b));
} elseif ($sortFlags & GETFILELIST_SORT_DIRNAME_DESC) {
return strnatcasecmp(dirname($b), dirname($a));
}
return strnatcasecmp($a, $b); // Default sort by name
};

// Helper function to recursively iterate over directories
$iterateDir = function ($dir) use (&$files, &$iterateDir, $sortFlags, $sortFunction) {
$contents = scandir($dir);
if ($contents === false) {
return;
}
foreach ($contents as $item) {
if ($item == '.' || $item == '..') {
continue;
}
$fullPath = $dir . DIRECTORY_SEPARATOR . $item;
if (is_dir($fullPath)) {
$iterateDir($fullPath);
} else {
$files[] = $fullPath;
}
}
};

$iterateDir($path);

// Sorting
usort($files, $sortFunction);

return $files;
}

?>
13 changes: 13 additions & 0 deletions files/api/lib/subdircheck.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

function is_sub_path($path, $parent_folder) {
$path = realpath($path);
$parent_folder = realpath($parent_folder);

if ($path !== false && $parent_folder !== false) {
return strpos($path, $parent_folder) === 0;
}

return false;
}
?>
17 changes: 9 additions & 8 deletions files/api/list.php
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
<?php
include_once(__DIR__."/lib/lib.php");
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
$files = scandir("/scans", SCANDIR_SORT_DESCENDING);
if(array_key_exists("num", $_GET)) {
$num = $_GET["num"];
} else {
$num = count($files);
}
$files = getFileList($SCANS_DIR, GETFILELIST_SORT_CREATEDATE_DESC);

$num = $_GET["num"] ?? count($files);
for ($i = 0; $i < $num; $i++) {
echo $files[$i]."<br>";
echo str_replace($SCANS_DIR."/", "", $files[$i])."<br>";
}
} else {
http_response_code(405);
die("Error: Method not allowed!");
}
?>
?>
16 changes: 16 additions & 0 deletions files/api/listfiles.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php
include_once(__DIR__."/lib/lib.php");

if ($_SERVER['REQUEST_METHOD'] == 'GET') {

$files = getFileList($SCANS_DIR, GETFILELIST_SORT_CREATEDATE_DESC);
for ($i = 0; $i < min(10, count($files)); $i++) {
$replaced = str_replace($SCANS_DIR."/", "", $files[$i]);
echo "<a class='listitem' href=/download.php?file=" . $replaced . ">" . $replaced . "</a><br>";
}
}
else {
http_response_code(405);
die("Error: Method not allowed!");
}
?>
Loading
Loading