New and updated version of old code.
This commit is contained in:
25
api/discoverScanners.php
Normal file
25
api/discoverScanners.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
function discoverScanners()
|
||||||
|
{
|
||||||
|
$scannersList = shell_exec('sudo scanimage -f "%d|%v %m"');
|
||||||
|
|
||||||
|
if($scannersList != "")
|
||||||
|
{
|
||||||
|
session_start();
|
||||||
|
$_SESSION["ScannersList"][0] = explode('|', $scannersList);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO / DEBUG - Fix this function
|
||||||
|
if(discoverScanners() === true) echo "OK";
|
||||||
|
else echo "Failed";
|
||||||
|
|
||||||
|
// TEST code
|
||||||
|
// session_start();
|
||||||
|
// $_SESSION["ScannersList"][0] = [ "xerox_mfp:libusb:003:010", "Samsung M2070" ];
|
||||||
|
// echo "OK";
|
||||||
|
|
||||||
|
?>
|
||||||
26
api/imageDownload.php
Normal file
26
api/imageDownload.php
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (isset($_GET['filename']))
|
||||||
|
{
|
||||||
|
require("../include/appConfig.php");
|
||||||
|
|
||||||
|
// Strip only file name form user string so he do not download system configs or whatnot
|
||||||
|
$file = $appConfig['imagesLocation'].basename($_GET['filename']);
|
||||||
|
|
||||||
|
if(!file_exists($file)) die('404 - File not found.');
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Set appropriate headers
|
||||||
|
header("Cache-Control: private");
|
||||||
|
header("Content-Description: File Transfer");
|
||||||
|
header("Content-Disposition: attachment; filename=".basename($_GET['filename']));
|
||||||
|
header("Content-Type: ".mime_content_type($file));
|
||||||
|
header("Content-Transfer-Encoding: binary");
|
||||||
|
|
||||||
|
// Read the file from disk
|
||||||
|
readfile($file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else echo "404 - File name not found.";
|
||||||
|
|
||||||
|
?>
|
||||||
9
api/rediscover.php
Normal file
9
api/rediscover.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
session_start();
|
||||||
|
session_unset();
|
||||||
|
session_destroy();
|
||||||
|
header("Location: ../index.php");
|
||||||
|
exit;
|
||||||
|
|
||||||
|
?>
|
||||||
126
api/scan.php
Normal file
126
api/scan.php
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
<?php
|
||||||
|
require("../include/appConfig.php");
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
////
|
||||||
|
//
|
||||||
|
/// Functions
|
||||||
|
//
|
||||||
|
////
|
||||||
|
|
||||||
|
function generateRandomString($length = 10)
|
||||||
|
{
|
||||||
|
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||||
|
$charactersLength = strlen($characters);
|
||||||
|
$randomString = '';
|
||||||
|
for ($i = 0; $i < $length; $i++)
|
||||||
|
{
|
||||||
|
$randomString .= $characters[rand(0, $charactersLength - 1)];
|
||||||
|
}
|
||||||
|
return $randomString;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkInput()
|
||||||
|
{
|
||||||
|
global $appConfig;
|
||||||
|
$checkOK = true;
|
||||||
|
|
||||||
|
if (isset($_GET['outputImageResolution']))
|
||||||
|
{
|
||||||
|
$found = false;
|
||||||
|
foreach ($appConfig['outputImageResolution'] as $item)
|
||||||
|
{
|
||||||
|
if($item[0] == $_GET['outputImageResolution']) $found = true;
|
||||||
|
}
|
||||||
|
if(!$found) $checkOK = false;
|
||||||
|
}
|
||||||
|
else $checkOK = false;
|
||||||
|
|
||||||
|
if (isset($_GET['outputImageColorDepth']))
|
||||||
|
{
|
||||||
|
$found = false;
|
||||||
|
foreach ($appConfig['outputImageColorDepth'] as $item)
|
||||||
|
{
|
||||||
|
if($item[0] == $_GET['outputImageColorDepth']) $found = true;
|
||||||
|
}
|
||||||
|
if(!$found) $checkOK = false;
|
||||||
|
}
|
||||||
|
else $checkOK = false;
|
||||||
|
|
||||||
|
if(isset($_GET['outputFileFormat']))
|
||||||
|
{
|
||||||
|
$found = false;
|
||||||
|
foreach ($appConfig['outputImageFormats'] as $item)
|
||||||
|
{
|
||||||
|
if($item[0] == $_GET['outputFileFormat']) $found = true;
|
||||||
|
}
|
||||||
|
if(!$found) $checkOK = false;
|
||||||
|
}
|
||||||
|
else $checkOK = false;
|
||||||
|
|
||||||
|
if (isset($_GET['inputPageSize']))
|
||||||
|
{
|
||||||
|
$found = false;
|
||||||
|
foreach ($appConfig['inputPageSizes'] as $item)
|
||||||
|
{
|
||||||
|
if($item[0] == $_GET['inputPageSize']) $found = true;
|
||||||
|
}
|
||||||
|
if(!$found) $checkOK = false;
|
||||||
|
}
|
||||||
|
else $checkOK = false;
|
||||||
|
|
||||||
|
if (isset($_GET['deviceID']))
|
||||||
|
{
|
||||||
|
$found = false;
|
||||||
|
foreach ($_SESSION['ScannersList'] as $item)
|
||||||
|
{
|
||||||
|
if($item[0] == $_GET['deviceID']) $found = true;
|
||||||
|
}
|
||||||
|
if(!$found) $checkOK = false;
|
||||||
|
}
|
||||||
|
else $checkOK = false;
|
||||||
|
|
||||||
|
return $checkOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNewFileName()
|
||||||
|
{
|
||||||
|
return 'scan-'.date('Ymd').'-'.generateRandomString().'.'.$_GET['outputFileFormat'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////
|
||||||
|
//
|
||||||
|
/// Logic
|
||||||
|
//
|
||||||
|
////
|
||||||
|
|
||||||
|
if(checkInput() !== true)
|
||||||
|
{
|
||||||
|
echo "400 - Bad request";
|
||||||
|
http_response_code(400);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
//Generate file name for scanned image
|
||||||
|
$filename = getNewFileName();
|
||||||
|
|
||||||
|
$scanCommand = "sudo scanimage --device-name ".$_GET['deviceID']." --format ".$_GET['outputFileFormat']." --resolution ".$_GET['outputImageResolution']." --mode ".$_GET['outputImageColorDepth']." > ".$appConfig['imagesLocation'].$filename;
|
||||||
|
|
||||||
|
|
||||||
|
////
|
||||||
|
//
|
||||||
|
/// Scanning start
|
||||||
|
//
|
||||||
|
////
|
||||||
|
|
||||||
|
//Prepare directory for scanned image
|
||||||
|
if(!is_dir($appConfig['imagesLocation'])) mkdir($appConfig['imagesLocation'], 777, true);
|
||||||
|
|
||||||
|
//Scan image
|
||||||
|
shell_exec($scanCommand);
|
||||||
|
|
||||||
|
//Output scanned image name indicating that scanning finished
|
||||||
|
echo $filename;
|
||||||
|
|
||||||
|
?>
|
||||||
BIN
assets/placeholderImage.png
Normal file
BIN
assets/placeholderImage.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
BIN
assets/placeholderImage.xcf
Normal file
BIN
assets/placeholderImage.xcf
Normal file
Binary file not shown.
31
include/appConfig.php
Normal file
31
include/appConfig.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$appConfig['imagesLocation'] = "/mnt/pool1/smb/Scanner/";
|
||||||
|
|
||||||
|
// Defaults for Samsung M2070
|
||||||
|
$appConfig['outputImageResolution'] = array(
|
||||||
|
[ "75", "75 DPI", false ],
|
||||||
|
[ "100", "100 DPI", false ],
|
||||||
|
[ "150", "150 DPI", false ],
|
||||||
|
[ "200", "200 DPI", false ],
|
||||||
|
[ "300", "300 DPI", true ],
|
||||||
|
[ "600", "600 DPI", false ]
|
||||||
|
);
|
||||||
|
$appConfig['outputImageColorDepth'] = array(
|
||||||
|
[ "Lineart", "Lineart", false ],
|
||||||
|
[ "Halftone", "Halftone", false ],
|
||||||
|
[ "Gray", "Gray", true ],
|
||||||
|
[ "Color", "Color", false ]
|
||||||
|
);
|
||||||
|
$appConfig['outputImageFormats'] = array(
|
||||||
|
[ "pnm", "PNM", false ],
|
||||||
|
[ "tiff", "TIFF(Image)", false ],
|
||||||
|
[ "png", "PNG(Image)", true ],
|
||||||
|
[ "jpeg", "JPEG(Image)", false ],
|
||||||
|
[ "pdf", "PDF", false ]
|
||||||
|
);
|
||||||
|
$appConfig['inputPageSizes'] = array(
|
||||||
|
[ "a4", "A4", true ]
|
||||||
|
);
|
||||||
|
|
||||||
|
?>
|
||||||
35
index.php
Normal file
35
index.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
if (isset($_SESSION["ScannersList"]))
|
||||||
|
{
|
||||||
|
header("Location: interface.php");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>saneAdmin</title>
|
||||||
|
|
||||||
|
<script src="js/appControl.js"></script>
|
||||||
|
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container text-center">
|
||||||
|
<h1>saneAdmin</h1>
|
||||||
|
|
||||||
|
<div id="scannerSearchProgress" class="progress mt-5" role="progressbar">
|
||||||
|
<div class="progress-bar" style="width: 0%"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="mt-2">Searching for scanners...</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
115
interface.php
Normal file
115
interface.php
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
if (!isset($_SESSION["ScannersList"]))
|
||||||
|
{
|
||||||
|
header("Location: interface.php");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
require("include/appConfig.php");
|
||||||
|
?>
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>saneAdmin</title>
|
||||||
|
|
||||||
|
<script src="js/appControl.js"></script>
|
||||||
|
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container text-center">
|
||||||
|
<h1><heavy>saneAdmin</heavy> - web based scanner control</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container mt-5">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<p class="fw-medium">Settings</p>
|
||||||
|
<hr>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="deviceIDFormSelect" class="form-label">Device:</label>
|
||||||
|
<select class="form-select" id="deviceIDFormSelect" aria-label="Device ID select">
|
||||||
|
<?php
|
||||||
|
foreach($_SESSION["ScannersList"] as $item)
|
||||||
|
echo "<option value='".$item[0]."'>".$item[1]."</option>";
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="outputImageResolutionFormSelect" class="form-label">Resolution of the scanned image:</label>
|
||||||
|
<select class="form-select" id="outputImageResolutionFormSelect" aria-label="Output image resolution select">
|
||||||
|
<?php
|
||||||
|
foreach($appConfig['outputImageResolution'] as $item)
|
||||||
|
{
|
||||||
|
if($item[2] === true) echo "<option value='".$item[0]."' selected>".$item[1]."</option>";
|
||||||
|
else echo "<option value='".$item[0]."'>".$item[1]."</option>";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="outputImageColorDepthFormSelect" class="form-label">Color depth of the scanned image:</label>
|
||||||
|
<select class="form-select" id="outputImageColorDepthFormSelect" aria-label="Output image color depth select">
|
||||||
|
<?php
|
||||||
|
foreach($appConfig['outputImageColorDepth'] as $item)
|
||||||
|
{
|
||||||
|
if($item[2] === true) echo "<option value='".$item[0]."' selected>".$item[1]."</option>";
|
||||||
|
else echo "<option value='".$item[0]."'>".$item[1]."</option>";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="outputFileFormatFormSelect" class="form-label">Output file format:</label>
|
||||||
|
<select class="form-select" id="outputFileFormatFormSelect" aria-label="Output file format select">
|
||||||
|
<?php
|
||||||
|
foreach($appConfig['outputImageFormats'] as $item)
|
||||||
|
{
|
||||||
|
if($item[2] === true) echo "<option value='".$item[0]."' selected>".$item[1]."</option>";
|
||||||
|
else echo "<option value='".$item[0]."'>".$item[1]."</option>";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="inputPageSizeFormSelect" class="form-label">Page size:</label>
|
||||||
|
<!-- Disabled as this option was removed in Debian 12 -->
|
||||||
|
<select class="form-select" id="inputPageSizeFormSelect" aria-label="Input page size select" disabled>
|
||||||
|
<option value="a4" selected>A4</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="d-grid gap-2">
|
||||||
|
<button onclick='scanImage();' class='btn btn-primary' type='button'>Scan</button>
|
||||||
|
<a href="api/rediscover.php" class="btn btn-primary mt-2" role="button">Rediscover device</a>
|
||||||
|
<a id="scannedImageDownloadButton" class="btn btn-primary mt-2" style="display: none;" role="button">Download image</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<p class="fw-medium">Scanned image preview</p>
|
||||||
|
<img id="scanPreview" src="assets/placeholderImage.png" class="img-fluid" alt="Scanned image preview">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div id="scanningAnimationModal" class="modal" tabindex="-1">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-body">
|
||||||
|
<p>Scanning in progress...</p>
|
||||||
|
<div class="progress" role="progressbar">
|
||||||
|
<div class="progress-bar progress-bar-striped progress-bar-animated" style="width: 100%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
79
js/appControl.js
Normal file
79
js/appControl.js
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
function discoverScanners(attemptID)
|
||||||
|
{
|
||||||
|
var xhttp = new XMLHttpRequest();
|
||||||
|
|
||||||
|
xhttp.onreadystatechange = function()
|
||||||
|
{
|
||||||
|
if (this.readyState == 4 && this.status == 200)
|
||||||
|
{
|
||||||
|
if(this.responseText == "OK")
|
||||||
|
{
|
||||||
|
location.href = "interface.php";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
console.log("[Scanner discovery(attempt " + attemptID + ")] Failed with message: " + this.responseText);
|
||||||
|
setTimeout(discoverScanners, 2000, ++attemptID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
xhttp.open("GET", "api/discoverScanners.php", true);
|
||||||
|
xhttp.send();
|
||||||
|
|
||||||
|
if(attemptID > 3)
|
||||||
|
{
|
||||||
|
var progressBarElement = document.getElementById("scannerSearchProgress");
|
||||||
|
progressBarElement.innerHTML = '<div class="progress-bar progress-bar-striped progress-bar-animated bg-warning" style="width: 100%; color: black;">Attempt ' + attemptID + '</div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function scannersDiscoveryController()
|
||||||
|
{
|
||||||
|
var progressBarElement = document.getElementById("scannerSearchProgress");
|
||||||
|
if(progressBarElement != null) progressBarElement.innerHTML = '<div class="progress-bar progress-bar-striped progress-bar-animated" style="width: 100%"></div>';
|
||||||
|
else return;
|
||||||
|
|
||||||
|
discoverScanners(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function scanImage()
|
||||||
|
{
|
||||||
|
const scanningAnimationModal = new bootstrap.Modal(document.getElementById('scanningAnimationModal'));
|
||||||
|
|
||||||
|
var deviceID = document.getElementById("deviceIDFormSelect").value;
|
||||||
|
var outputImageResolution = document.getElementById("outputImageResolutionFormSelect").value;
|
||||||
|
var outputImageColorDepth = document.getElementById("outputImageColorDepthFormSelect").value;
|
||||||
|
var outputFileFormat = document.getElementById("outputFileFormatFormSelect").value;
|
||||||
|
var inputPageSize = document.getElementById("inputPageSizeFormSelect").value;
|
||||||
|
|
||||||
|
var xhttp = new XMLHttpRequest();
|
||||||
|
|
||||||
|
xhttp.onreadystatechange = function()
|
||||||
|
{
|
||||||
|
// TODO / DEBUG - Enable this
|
||||||
|
if (this.readyState == 4 && this.status == 200)
|
||||||
|
{
|
||||||
|
var scannedFileName = this.responseText;
|
||||||
|
|
||||||
|
var scannedImagePreview = document.getElementById("scanPreview");
|
||||||
|
scannedImagePreview.src = "api/imageDownload.php?filename=" + scannedFileName;
|
||||||
|
scannedImagePreview.alt = scannedFileName;
|
||||||
|
|
||||||
|
var scannedImageDownloadButton = document.getElementById("scannedImageDownloadButton");
|
||||||
|
scannedImageDownloadButton.href = "api/imageDownload.php?filename=" + scannedFileName;
|
||||||
|
scannedImageDownloadButton.style = "display: block;";
|
||||||
|
|
||||||
|
scanningAnimationModal.hide();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
xhttp.open("GET", "api/scan.php?outputImageResolution=" + outputImageResolution + "&outputImageColorDepth=" + outputImageColorDepth + "&outputFileFormat=" + outputFileFormat + "&inputPageSize=" + inputPageSize + "&deviceID=" + deviceID, true);
|
||||||
|
xhttp.send();
|
||||||
|
|
||||||
|
scanningAnimationModal.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", (event) => { scannersDiscoveryController(); });
|
||||||
Reference in New Issue
Block a user