Skip to content

Commit

Permalink
Merge pull request #15 from philippderdiedas/pull-request
Browse files Browse the repository at this point in the history
Big update (second try)
  • Loading branch information
PhilippMundhenk authored Feb 25, 2024
2 parents fc336d7 + af3d046 commit a986541
Show file tree
Hide file tree
Showing 18 changed files with 466 additions and 227 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
name: Create and publish a Docker image
name: Create and publish a Docker image on master

# Configures this workflow to run every time a change is pushed to the branch called `master`.
on:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publishBranches.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
name: Create and publish a Docker image
name: Create and publish a Docker image on a branch

# Configures this workflow to run every time a change is pushed to the branch called `master`.
on:
Expand Down
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
51 changes: 24 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ services:
- /path/on/host:/scans
ports:
- 54925:54925/udp # mandatory, for scanner tools
- 54921:54921 # mandatory, for scanner tools
- 161:161/udp # mandatory, for scanner tools
environment:
- NAME=Scanner
Expand Down Expand Up @@ -86,7 +85,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,16 +101,13 @@ 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:false) (see below) |
| WEBSERVER_PING_ENABLE | optional | activates ping service to check if scanner offline |
| 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 |
### FTPS upload
Expand Down Expand Up @@ -161,12 +158,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 +178,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 +193,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 +206,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
27 changes: 15 additions & 12 deletions files/api/download.php
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
<?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!");
}
?>
?>
Loading

0 comments on commit a986541

Please sign in to comment.