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