wok annotate sane-backends/stuff/tazpanel/sane.cgi @ rev 18237

sane-backends: add tazpanel/sane.cgi
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sat Jul 25 13:48:18 2015 +0200 (2015-07-25)
parents
children 4ea96657834e
rev   line source
pascal@18237 1 #!/bin/sh
pascal@18237 2 #
pascal@18237 3 # Scanner CGI interface - Scan documents via a browser
pascal@18237 4 #
pascal@18237 5 # (C) 2015 SliTaz GNU/Linux - BSD License
pascal@18237 6 #
pascal@18237 7
pascal@18237 8 # Common functions from libtazpanel
pascal@18237 9 . lib/libtazpanel
pascal@18237 10 get_config
pascal@18237 11
pascal@18237 12 #------
pascal@18237 13 # menu
pascal@18237 14 #------
pascal@18237 15
pascal@18237 16 case "$1" in
pascal@18237 17 menu)
pascal@18237 18 TEXTDOMAIN_original=$TEXTDOMAIN
pascal@18237 19 export TEXTDOMAIN='sane'
pascal@18237 20
pascal@18237 21 cat <<EOT
pascal@18237 22 <li><a data-icon="text" href="sane.cgi"$(groups | grep -q scanner ||
pascal@18237 23 echo ' data-root')>$(_ 'Scanner')</a></li>
pascal@18237 24 EOT
pascal@18237 25 export TEXTDOMAIN=$TEXTDOMAIN_original
pascal@18237 26 exit
pascal@18237 27 esac
pascal@18237 28
pascal@18237 29 TITLE="$(_ 'TazPanel - Hardware') - $(_ 'Scanner')"
pascal@18237 30
pascal@18237 31 inrange() {
pascal@18237 32 local n=$1
pascal@18237 33 [ $1 -lt $2 ] && n=$2
pascal@18237 34 [ $1 -gt $3 ] && n=$3
pascal@18237 35 echo $n
pascal@18237 36 }
pascal@18237 37
pascal@18237 38 getgeometry() {
pascal@18237 39 CMD=""
pascal@18237 40 for i in l t x y ; do
pascal@18237 41 j=$(inrange $(xPOST geometry_$i) $(xPOST ${i}_min) $(xPOST ${i}_max))
pascal@18237 42 eval "geometry_$i=$j"
pascal@18237 43 CMD="$CMD -$i $j"
pascal@18237 44 # convert -crop XxY+L+T -resize XxY
pascal@18237 45 done
pascal@18237 46 for i in mode source contrast brightness ; do
pascal@18237 47 [ "$(xPOST $i)" ] && CMD="$CMD --$i '$(xPOST $i)'"
pascal@18237 48 done
pascal@18237 49 resolution=${1:-0}
pascal@18237 50 if [ $resolution -eq 0 ]; then
pascal@18237 51 resolution=$(xPOST res_min)
pascal@18237 52 width=$(GET width)
pascal@18237 53 [ ${geometry_x:-0} -le 0 ] && geometry_x=$(xPOST x_max)
pascal@18237 54 while [ $((${resolution:=150} * ${geometry_x%.*})) -lt ${width:-8192} ]; do
pascal@18237 55 resolution=$(($resolution * 2))
pascal@18237 56 done
pascal@18237 57 fi
pascal@18237 58 [ -d tmp ] || ln -s /tmp tmp
pascal@18237 59 case "$device" in
pascal@18237 60 fake*) echo "cat /usr/share/images/slitaz-background.jpg" ;;
pascal@18237 61 *) echo "scanimage -d '$(echo $device | sed 's/,.*//')' --resolution '$(inrange $resolution $(xPOST res_min) $(xPOST res_max))dpi'$CMD"
pascal@18237 62 esac
pascal@18237 63 }
pascal@18237 64
pascal@18237 65 imgformat() {
pascal@18237 66 tmp=$(mktemp -u -t tazsane.XXXXXX)
pascal@18237 67 while read key name type exe pkg cmd ; do
pascal@18237 68 case "$key" in
pascal@18237 69 \#*) continue
pascal@18237 70 esac
pascal@18237 71 case "$1" in
pascal@18237 72 list)
pascal@18237 73 echo -n "<option value=\"$key\""
pascal@18237 74 [ "$(which $exe 2> /dev/null)" ] ||
pascal@18237 75 echo -n " disabled title=\"$exe not found: install $pkg\""
pascal@18237 76 [ "$key" == "pnm" ] &&
pascal@18237 77 echo -n " title=\"not supported by most browsers\""
pascal@18237 78 echo ">$key" ;;
pascal@18237 79 *)
pascal@18237 80 case "$key" in
pascal@18237 81 $(xPOST format)|'*')
pascal@18237 82 case "$HTTP_USER_AGENT" in
pascal@18237 83
pascal@18237 84 # Tazweb has no download support
pascal@18237 85 TazWe*) rm -f /tmp/$name
pascal@18237 86 eval "$(getgeometry $(xPOST resolution)) $cmd >/tmp/$name" 2> $tmp.err
pascal@18237 87 if [ -s /tmp/$name ]; then
pascal@18237 88 info="Stored in /tmp/$name ($(stat -c %s /tmp/$name) bytes)."
pascal@18237 89 else
pascal@18237 90 error="$(sed 's|$|<br />|' $tmp.err)"
pascal@18237 91 [ "$error" ] || error="I/O error"
pascal@18237 92 fi
pascal@18237 93 rm -f $tmp.* ;;
pascal@18237 94
pascal@18237 95 # Others should work
pascal@18237 96 *) header "Content-Type: $type" \
pascal@18237 97 "Content-Disposition: attachment; filename=$name" \
pascal@18237 98
pascal@18237 99 eval "$(getgeometry $(xPOST resolution)) $cmd"
pascal@18237 100 rm -f $tmp.*
pascal@18237 101 exit ;;
pascal@18237 102 esac ;;
pascal@18237 103 esac ;;
pascal@18237 104 esac
pascal@18237 105 done <<EOT
pascal@18237 106 png tazsane.png image/png convert imagemagick > $tmp.pnm; convert $tmp.pnm png:-
pascal@18237 107 jpeg tazsane.jpg image/jpeg convert imagemagick > $tmp.pnm; convert $tmp.pnm jpg:-
pascal@18237 108 jpeg2000 tazsane.jp2 image/jpeg2000-image convert imagemagick > $tmp.pnm; convert $tmp.pnm jp2:-
pascal@18237 109 tiff tazsane.tiff image/tiff convert imagemagick > $tmp.pnm; convert $tmp.pnm tiff:-
pascal@18237 110 ps tazsane.ps application/postscript convert imagemagick > $tmp.pnm; convert -page A4+0+0 $tmp.pnm ps:-
pascal@18237 111 pdf tazsane.pdf image/pdf convert imagemagick > $tmp.pnm; convert $tmp.pnm pdf:-
pascal@18237 112 ocr1 tazsane-OCR1.txt text/plain gocr gocr | gocr -
pascal@18237 113 ocr2 tazsane-OCR2.txt text/plain tesseract tesseract-ocr | tesseract stdin stdout
pascal@18237 114 pnm tazsane.pnm image/pnm true slitaz
pascal@18237 115 EOT
pascal@18237 116 }
pascal@18237 117
pascal@18237 118 xPOST() {
pascal@18237 119 [ "$preview" == "reset" ] || POST $@
pascal@18237 120 }
pascal@18237 121
pascal@18237 122 tmpreview="$(POST tmpreview)"
pascal@18237 123 find tmp/ -name 'tazsane*' -mmin +60 -prune -exec rm -f {} \;
pascal@18237 124
pascal@18237 125 device="$(POST device)"
pascal@18237 126 preview="$(POST preview)"
pascal@18237 127 info=""
pascal@18237 128 error=""
pascal@18237 129
pascal@18237 130 case " $(POST) " in
pascal@18237 131 *\ reset\ *)
pascal@18237 132 unset device tmpreview
pascal@18237 133 preview="reset" ;;
pascal@18237 134 *\ preview\ *)
pascal@18237 135 [ "$tmpreview" ] || tmpreview=$(mktemp -u -t tazsane.XXXXXX).png
pascal@18237 136 tmp=$(mktemp -u -t tazsane.XXXXXX)
pascal@18237 137 eval "$(getgeometry)" > $tmp.pnm 2> $tmp.err
pascal@18237 138 if [ -s "$tmp.pnm" ]; then
pascal@18237 139 convert $tmp.pnm $tmpreview > /dev/null 2>&1 ||
pascal@18237 140 cp $tmp.pnm $tmpreview
pascal@18237 141 else
pascal@18237 142 error="$(sed 's|$|<br />|' $tmp.err)"
pascal@18237 143 rm -f $tmpreview
pascal@18237 144 fi
pascal@18237 145 rm -f $tmp.pnm $tmp.err ;;
pascal@18237 146 *\ scan\ *)
pascal@18237 147 imgformat download ;;
pascal@18237 148 esac
pascal@18237 149
pascal@18237 150 header
pascal@18237 151 xhtml_header
pascal@18237 152 [ -n "$error" ] && msg warn "$error"
pascal@18237 153 [ -n "$info" ] && msg tip "$info"
pascal@18237 154 if [ -z "$device" ]; then
pascal@18237 155 [ -s sane-fake.log ] && all="$(sed 's/|/\n/g' sane-fake.log)" ||
pascal@18237 156 all="$(scanimage -f '%d,%v %m|' | sed 's/|/\n/g')"
pascal@18237 157 case "$(echo "$all" | wc -l)" in
pascal@18237 158 1) if [ -z "$all" ]; then
pascal@18237 159 msg warn 'No scanner found'
pascal@18237 160 xhtml_footer
pascal@18237 161 exit 0
pascal@18237 162 fi
pascal@18237 163 device="${all%|}" ;;
pascal@18237 164 *) cat <<EOT
pascal@18237 165 <section>
pascal@18237 166 <header>
pascal@18237 167 <form name="scanner" method="post">
pascal@18237 168 Scanner
pascal@18237 169 <select name="device" size=1>
pascal@18237 170 EOT
pascal@18237 171 echo "$all" | awk -F, '{ if (NF > 0) print "<option value=\"" $0 "\">" 1+i++ " - " $2 }'
pascal@18237 172 cat <<EOT
pascal@18237 173 </select>
pascal@18237 174 <button data-icon="start">$(_ "Continue")</button>
pascal@18237 175 </form>
pascal@18237 176 </header>
pascal@18237 177 </section>
pascal@18237 178 EOT
pascal@18237 179 xhtml_footer
pascal@18237 180 exit 0 ;;
pascal@18237 181 esac
pascal@18237 182 fi
pascal@18237 183
pascal@18237 184 cat <<EOT
pascal@18237 185 <section>
pascal@18237 186 <form name="parameters" method="post">
pascal@18237 187 <script language="JavaScript" type="text/javascript">
pascal@18237 188 <!--
pascal@18237 189 function new_width() {
pascal@18237 190 document.parameters.action = "?width="+document.width
pascal@18237 191 }
pascal@18237 192
pascal@18237 193 window.onresize = new_width
pascal@18237 194 new_width()
pascal@18237 195 -->
pascal@18237 196 </script>
pascal@18237 197
pascal@18237 198 <header>
pascal@18237 199 $(echo $device | sed 's/.*,//')
pascal@18237 200 <div class="float-right">
pascal@18237 201 <button name="scan" data-icon="start">$(_ "Scan")</button>
pascal@18237 202 <button name="reset" data-icon="stop">$(_ "Reset")</button>
pascal@18237 203 <button name="preview" data-icon="view">$(_ "Preview")</button>
pascal@18237 204 </div>
pascal@18237 205 </header>
pascal@18237 206
pascal@18237 207 <table class="wide" border="2" cellpadding="8" cellspacing="0">
pascal@18237 208 <tr>
pascal@18237 209 <td>Format
pascal@18237 210 <select name="format" size=1>
pascal@18237 211 $(imgformat list)
pascal@18237 212 </select>
pascal@18237 213 </td>
pascal@18237 214 EOT
pascal@18237 215
pascal@18237 216 if [ "$(xPOST params)" ]; then
pascal@18237 217 params="$(xPOST params | uudecode)"
pascal@18237 218 else
pascal@18237 219 params="$({
pascal@18237 220 cat "$(echo $device | sed 's/,.*//').log" 2> /dev/null ||
pascal@18237 221 scanimage --help -d "$(echo $device | sed 's/,.*//')"
pascal@18237 222 } | awk '
pascal@18237 223 function minmax()
pascal@18237 224 {
pascal@18237 225 if (match($2,"[0-9]")) {
pascal@18237 226 i=$2; sub(/\.\..*/,"",i)
pascal@18237 227 j=$2; sub(/.*\.\./,"",j)
pascal@18237 228 sub(/\..*/,"",j); sub(/[dm%].*/,"",j)
pascal@18237 229 k=$0; sub(/.* \[/,"",k); sub(/\].*/,"",k)
pascal@18237 230 print $1 " " int(k) " " int(i) " " int(j)
pascal@18237 231 }
pascal@18237 232 }
pascal@18237 233
pascal@18237 234 function enum()
pascal@18237 235 {
pascal@18237 236 i=$0
pascal@18237 237 if (index(i,"|")) {
pascal@18237 238 sub(/^ *--*[a-z]* */,"",i)
pascal@18237 239 sub(/dpi .*/,"",i); gsub(/ \[.*\].*/,"",i)
pascal@18237 240 k=$0; sub(/.* \[/,"",k); sub(/\].*/,"",k)
pascal@18237 241 gsub(/ /,"=",k)
pascal@18237 242 print $1 " " k " enum " i
pascal@18237 243 }
pascal@18237 244 else minmax()
pascal@18237 245 }
pascal@18237 246
pascal@18237 247 /Options specific to device/ { parse=1 }
pascal@18237 248 {
pascal@18237 249 if (parse != 1) next
pascal@18237 250 if (/\[inactive\]/) next
pascal@18237 251 if (match("-l-t-x-y", $1)) minmax()
pascal@18237 252 if (match("--resolution--brightness--contrast--source--mode", $1)) enum()
pascal@18237 253 }
pascal@18237 254 ')"
pascal@18237 255 fi
pascal@18237 256 output="$(echo "$params" | while read name def min max ; do
pascal@18237 257 name="${name##*-}"
pascal@18237 258 def="${def//=/ }"
pascal@18237 259 if [ "$min" == "enum" ]; then
pascal@18237 260 res_min=1000000
pascal@18237 261 res_max=0
pascal@18237 262 echo "<td>$name"
pascal@18237 263 echo -n "<select name=\"$name\" size=1"
pascal@18237 264 [ "$name" == "resolution" ] && echo -n " onchange=showGeometry()"
pascal@18237 265 echo ">"
pascal@18237 266 IFS="|"; set -- $max ; unset IFS
pascal@18237 267 while [ "$1" ]; do
pascal@18237 268 echo -n "<option value=\"$1\""
pascal@18237 269 [ "$(xPOST $name)" == "$1" ] && echo -n " selected"
pascal@18237 270 [ -z "$(xPOST $name)" -a "$def" == "$1" ] && echo -n " selected"
pascal@18237 271 echo ">$(_ "$1")"
pascal@18237 272 if [ "$name" == "resolution" ]; then
pascal@18237 273 [ $res_max -lt $1 ] && res_max=$1
pascal@18237 274 [ $res_min -gt $1 ] && res_min=$1
pascal@18237 275 fi
pascal@18237 276 shift
pascal@18237 277 done
pascal@18237 278 echo "</select>"
pascal@18237 279 else
pascal@18237 280 [ "$(xPOST $name)" ] && def=$(xPOST $name)
pascal@18237 281 [ $def -lt $min ] && def=$min
pascal@18237 282 [ $def -gt $max ] && def=$max
pascal@18237 283 f="$(_ "$name")<input name=\"$name\" value=\"$def\""
pascal@18237 284 u=""
pascal@18237 285 case "$name" in
pascal@18237 286 x|y|l|t) cat <<EOT
pascal@18237 287 :${name}_max=$max
pascal@18237 288 <input type="hidden" name="${name}_min" value="$min">
pascal@18237 289 <input type="hidden" name="${name}_max" value="$max">
pascal@18237 290 EOT
pascal@18237 291 while read name2 n2 id val; do
pascal@18237 292 [ "$name" == "$name2" ] || continue
pascal@18237 293 [ "$(xPOST geometry_$name)" ] &&
pascal@18237 294 val="$(xPOST geometry_$name)"
pascal@18237 295 f="$(_ "$n2")<input name=\"geometry_$name\" id=\"$id\" value=\"$val\""
pascal@18237 296 u="&nbsp;mm"
pascal@18237 297 break
pascal@18237 298 done <<EOT
pascal@18237 299 l X-Offset x 0
pascal@18237 300 t Y-Offset y 0
pascal@18237 301 x Width width $max
pascal@18237 302 y Height height $max
pascal@18237 303 EOT
pascal@18237 304 [ "$newline" ] || echo "</tr><tr>"
pascal@18237 305 newline=$name
pascal@18237 306 esac
pascal@18237 307 [ "$name" == "resolution" ] && f="$f onchange=showGeometry()"
pascal@18237 308 echo "<td>$f type=\"text\" title=\"$min .. $max\" size=4 maxlength=4>$u"
pascal@18237 309 res_min=$min
pascal@18237 310 res_max=$max
pascal@18237 311 fi
pascal@18237 312 case "$name" in
pascal@18237 313 resolution) cat <<EOT
pascal@18237 314 <input type="hidden" name="res_min" value="$res_min">
pascal@18237 315 <input type="hidden" name="res_max" value="$res_max">
pascal@18237 316 &nbsp;dpi
pascal@18237 317 EOT
pascal@18237 318 esac
pascal@18237 319 echo "</td>"
pascal@18237 320 done)"
pascal@18237 321 echo "$output" | sed '/^:/d'
pascal@18237 322
pascal@18237 323 org_x=$(xPOST geometry_x); [ "$org_x" ] || org_x=$(echo "$output" | sed '/^:x_max=/!d;s/.*=//')
pascal@18237 324 org_y=$(xPOST geometry_y); [ "$org_y" ] || org_y=$(echo "$output" | sed '/^:y_max=/!d;s/.*=//')
pascal@18237 325
pascal@18237 326 cat <<EOT
pascal@18237 327 </tr>
pascal@18237 328 </table>
pascal@18237 329 <input type="hidden" name="tmpreview" value="$tmpreview">
pascal@18237 330 <input type="hidden" name="device" value="$device">
pascal@18237 331 <input type="hidden" name="params" value="$(echo "$params" | uuencode -m -)">
pascal@18237 332 <script language="JavaScript" type="text/javascript">
pascal@18237 333 <!--
pascal@18237 334 function setGeometry(x,y) {
pascal@18237 335 document.parameters.geometry_x.value = x;
pascal@18237 336 document.parameters.geometry_y.value = y;
pascal@18237 337 cropSetFrameByInput();
pascal@18237 338 }
pascal@18237 339
pascal@18237 340 function showGeometry() {
pascal@18237 341 var resolution = document.parameters.resolution.value;
pascal@18237 342 if (resolution) {
pascal@18237 343 resolution /= 25.4;
pascal@18237 344 var x = Math.floor(document.parameters.geometry_x.value * resolution);
pascal@18237 345 var y = Math.floor(document.parameters.geometry_y.value * resolution);
pascal@18237 346 alert((Math.round(x * y / 100000)/10) + ' Mpixels\n' + x + 'x' + y);
pascal@18237 347 }
pascal@18237 348 }
pascal@18237 349 -->
pascal@18237 350 </script>
pascal@18237 351
pascal@18237 352 <footer align="center">
pascal@18237 353 EOT
pascal@18237 354 awk -vox=$org_x -voy=$org_y 'END {
pascal@18237 355 x=210*4; y=297*4; n=0; cnt=0;
pascal@18237 356 while (cnt < 9) {
pascal@18237 357 if (ox +1 >= x && oy +1 >= y) {
pascal@18237 358 print "&nbsp;<a href=\"javascript:setGeometry(" x "," y ")\">DIN-A" n "</a>"
pascal@18237 359 cnt++
pascal@18237 360 }
pascal@18237 361 if (ox +1 >= x && oy +1 >= y) {
pascal@18237 362 print "&nbsp;<a href=\"javascript:setGeometry(" y "," x ")\">DIN-A" n "L</a>"
pascal@18237 363 cnt++
pascal@18237 364 }
pascal@18237 365 tmp=x; x=y/2; y=tmp
pascal@18237 366 n++
pascal@18237 367 }
pascal@18237 368 }' < /dev/null
pascal@18237 369
pascal@18237 370 cat <<EOT
pascal@18237 371 </footer>
pascal@18237 372 </form>
pascal@18237 373 </section>
pascal@18237 374 EOT
pascal@18237 375
pascal@18237 376 [ -s "$tmpreview" ] && cat <<EOT
pascal@18237 377 <div margin="15px" style="overflow-x: auto">
pascal@18237 378 <script type="text/javascript" src="lib/crop.js"></script>
pascal@18237 379 <img src="$tmpreview" onload=cropInit(this,'x','y','width','height')>
pascal@18237 380 </div>
pascal@18237 381 EOT
pascal@18237 382 xhtml_footer