2021-12-19 20:18:58 +00:00
|
|
|
|
use path
|
|
|
|
|
use re
|
|
|
|
|
use str
|
|
|
|
|
|
|
|
|
|
fn is-pdf {|file|
|
|
|
|
|
eq (path:ext $file) '.pdf'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn exist {|file|
|
|
|
|
|
or (path:is-dir &follow-symlink=$true $file) (path:is-regular &follow-symlink=$true $file)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn not-exist {|file|
|
|
|
|
|
not (exist $file)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn is-pdf-exist {|file|
|
|
|
|
|
and (is-pdf $file) (exist $file)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn is-number {|v|
|
|
|
|
|
re:match '^\d+$' (to-string $v)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn is-page-selection {|v|
|
|
|
|
|
re:match '^(r?\d+|z)(-(r?\d+|z))?(,(r?\d+|z)(-(r?\d+|z))?)*(:(even|odd))?$' (to-string $v)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn is-rotate-selection {|v|
|
|
|
|
|
re:match '^(\+|-)?\d+(:(r?\d+|z)(-(r?\d+|z))?(,(r?\d+|z)(-(r?\d+|z))?)*(:(even|odd))?)?$' (to-string $v)
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-24 13:50:36 +00:00
|
|
|
|
fn is-object {|v|
|
|
|
|
|
re:match '^ \d+\ 0\ R$' $v
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-19 20:18:58 +00:00
|
|
|
|
fn is-selection {|v|
|
|
|
|
|
or (is-page-selection $v) (is-rotate-selection $v)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn version {|in|
|
|
|
|
|
var version = (head -n 1 $in)
|
|
|
|
|
set version @_ = (str:split "\r" $version)
|
|
|
|
|
str:trim-prefix $version '%PDF-'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn json {|in|
|
|
|
|
|
qpdf $in --json | from-json
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn form {|in|
|
|
|
|
|
var json = (json $in)
|
|
|
|
|
put $json[acroform]
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-22 12:31:39 +00:00
|
|
|
|
fn encryption {|in|
|
|
|
|
|
var json = (json $in)
|
|
|
|
|
put $json[encrypt]
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-19 20:18:58 +00:00
|
|
|
|
fn objects {|in|
|
|
|
|
|
var json = (json $in)
|
|
|
|
|
put $json[objects]
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-24 13:50:36 +00:00
|
|
|
|
fn -format {|dict o|
|
|
|
|
|
var t = (kind-of $o)
|
|
|
|
|
if (eq $t string) {
|
|
|
|
|
if (has-key $dict $o) {
|
|
|
|
|
set o = $dict[$o]
|
|
|
|
|
}
|
|
|
|
|
} elif (eq $t list) {
|
|
|
|
|
set @o = (all $o | each {|e|
|
|
|
|
|
if (has-key $dict $e) {
|
|
|
|
|
put $dict[$e]
|
|
|
|
|
} else {
|
|
|
|
|
put $e
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
} elif (eq $t map) {
|
|
|
|
|
keys $o | each {|k|
|
|
|
|
|
set o[$k] = (-format $dict $o[$k])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
put $o
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn -deep {|&dict=$nil objects @keys|
|
|
|
|
|
if (== (count $keys) 0) {
|
|
|
|
|
if (not-eq $dict $nil) {
|
|
|
|
|
put (-format $dict $objects) $true
|
|
|
|
|
} else {
|
|
|
|
|
put $objects $true
|
|
|
|
|
}
|
2021-12-19 20:18:58 +00:00
|
|
|
|
return
|
|
|
|
|
}
|
2021-12-24 13:50:36 +00:00
|
|
|
|
if (not-eq $dict $nil) {
|
|
|
|
|
set objects = (-format $dict $objects)
|
|
|
|
|
}
|
|
|
|
|
var id @next = $@keys
|
|
|
|
|
var t = (kind-of $objects)
|
|
|
|
|
if (eq $t map) {
|
|
|
|
|
if (has-key $objects $id) {
|
|
|
|
|
-deep &dict=$dict $objects[$id] $@next
|
2021-12-19 20:18:58 +00:00
|
|
|
|
}
|
2021-12-24 13:50:36 +00:00
|
|
|
|
} elif (eq $t list) {
|
|
|
|
|
if (and (is-number $id) (< $id (count $objects))) {
|
|
|
|
|
-deep &dict=$dict $objects[$id] $@next
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
put $nil $false
|
2021-12-19 20:18:58 +00:00
|
|
|
|
}
|
2021-12-24 13:50:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn -object {|&extend=$false objects id|
|
|
|
|
|
var dict = $nil
|
|
|
|
|
if $extend {
|
|
|
|
|
set dict = $objects
|
|
|
|
|
}
|
|
|
|
|
var o _ = (-deep &dict=$dict $objects $id)
|
2021-12-19 20:18:58 +00:00
|
|
|
|
put $o
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-24 13:50:36 +00:00
|
|
|
|
fn deep {|&extend=$false in @keys|
|
|
|
|
|
var dict = (objects $in)
|
|
|
|
|
if $extend {
|
|
|
|
|
-deep &dict=$dict $dict $@keys
|
|
|
|
|
} else {
|
|
|
|
|
-deep $dict $@keys
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn contains {|in @keys|
|
|
|
|
|
var _ ok = (deep $in $@keys)
|
|
|
|
|
put $ok
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn value {|&extend=$false in @keys|
|
|
|
|
|
var v _ = (deep &extend=$extend $in $@keys)
|
|
|
|
|
put $v
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-19 20:18:58 +00:00
|
|
|
|
fn object {|&extend=$false in key|
|
2021-12-24 13:50:36 +00:00
|
|
|
|
-object &extend=$extend (objects $in) $key
|
2021-12-19 20:18:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-12-24 13:50:36 +00:00
|
|
|
|
fn -filter {|&extend=$false objects cond|
|
|
|
|
|
var out = [&]
|
2021-12-19 20:18:58 +00:00
|
|
|
|
keys $objects | each {|k|
|
2021-12-24 13:50:36 +00:00
|
|
|
|
var o = (-object &extend=$extend $objects $k)
|
2021-12-19 20:18:58 +00:00
|
|
|
|
if ($cond $o) {
|
2021-12-24 13:50:36 +00:00
|
|
|
|
set out[$k] = $o
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
put $out
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn filter {|&extend=$false in cond|
|
|
|
|
|
-filter &extend=$extend (objects $in) $cond
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn font-filter {|o|
|
|
|
|
|
and ^
|
|
|
|
|
(eq (kind-of $o) map) ^
|
|
|
|
|
(has-key $o /Type) ^
|
|
|
|
|
(eq $o[/Type] /Font)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn fonts {|in|
|
|
|
|
|
var dict = (objects $in)
|
|
|
|
|
var fonts = (-filter $dict $font-filter~)
|
|
|
|
|
keys $fonts | each {|id|
|
|
|
|
|
var f = $fonts[$id]
|
|
|
|
|
keys $f | each {|k|
|
|
|
|
|
var v = $f[$k]
|
|
|
|
|
if (has-key $dict $v) {
|
|
|
|
|
set f[$k] = $dict[$v]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
var fd = $f[/FontDescriptor]
|
|
|
|
|
keys $fd | each {|k|
|
|
|
|
|
var v = $fd[$k]
|
|
|
|
|
if (and (not-eq $k /FontFile2) (has-key $dict $v)) {
|
|
|
|
|
set fd[$k] = $dict[$v]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
set f[/FontDescriptor] = $fd
|
|
|
|
|
set f[id] = $id
|
|
|
|
|
put $f
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn image-filter {|o|
|
|
|
|
|
and ^
|
|
|
|
|
(eq (kind-of $o) map) ^
|
|
|
|
|
(has-key $o /Subtype) ^
|
|
|
|
|
(eq $o[/Subtype] /Image)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn images {|in|
|
|
|
|
|
var json = (json $in)
|
|
|
|
|
var dict = $json[objects]
|
|
|
|
|
all $json[pages] | each {|p|
|
|
|
|
|
var n = $p[pageposfrom1]
|
|
|
|
|
all $p[images] | each {|i|
|
|
|
|
|
var id = $i[object]
|
|
|
|
|
var img = (-object $dict $id)
|
|
|
|
|
keys $img | each {|k|
|
|
|
|
|
var v = $img[$k]
|
|
|
|
|
if (has-key $dict $v) {
|
|
|
|
|
set img[$k] = $dict[$v]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (has-key $img /ColorSpace) {
|
|
|
|
|
var @cs = (all $img[/ColorSpace] | each {|v|
|
|
|
|
|
if (has-key $dict $v) {
|
|
|
|
|
put $dict[$v]
|
|
|
|
|
} else {
|
|
|
|
|
put $v
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
set img[/ColorSpace] = $cs
|
|
|
|
|
}
|
|
|
|
|
if (has-key $img /DecodeParms) {
|
|
|
|
|
var dp = $img[/DecodeParms]
|
|
|
|
|
keys $dp | each {|k|
|
|
|
|
|
var v = $dp[$k]
|
|
|
|
|
if (has-key $dict $v) {
|
|
|
|
|
set dp[$k] = $dict[$v]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
set img[/DecodeParms] = $dp
|
|
|
|
|
}
|
|
|
|
|
set img[id] = $id
|
|
|
|
|
set img[page] = $n
|
|
|
|
|
set img[name] = $i[name]
|
|
|
|
|
put $img
|
2021-12-19 20:18:58 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-24 13:50:36 +00:00
|
|
|
|
fn trailer {|&extend=$false in|
|
|
|
|
|
object &extend=$extend $in 'trailer'
|
2021-12-19 20:18:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn pages {|in|
|
|
|
|
|
var json = (json $in)
|
|
|
|
|
put $json[pages]
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-22 12:31:39 +00:00
|
|
|
|
fn page {|in nb|
|
|
|
|
|
put (pages $in)[(- $nb 1)]
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-19 20:18:58 +00:00
|
|
|
|
fn nb-pages {|in|
|
|
|
|
|
qpdf --show-npages $in
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-24 13:50:36 +00:00
|
|
|
|
fn attachments {|in|
|
|
|
|
|
var data = []
|
|
|
|
|
var json = (json $in)
|
|
|
|
|
var attachments = $json[attachments]
|
|
|
|
|
if (> (count $attachments) 0) {
|
|
|
|
|
set @data = (qpdf --list-attachments $in | eawk {|_ f @_|
|
|
|
|
|
put $f
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
put $data
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-19 20:18:58 +00:00
|
|
|
|
fn parse-selection {|@selection|
|
|
|
|
|
var out = []
|
|
|
|
|
var in = $nil
|
|
|
|
|
each {|e|
|
|
|
|
|
if (is-pdf $e) {
|
|
|
|
|
if (not-exist $e) {
|
|
|
|
|
fail (printf '%s: le fichier n’existe pas' $e)
|
|
|
|
|
}
|
|
|
|
|
if (not-eq $in $nil) {
|
|
|
|
|
set @out = $@out $in
|
|
|
|
|
}
|
|
|
|
|
set in = [
|
|
|
|
|
&file=$e
|
|
|
|
|
&rotate=$nil
|
|
|
|
|
&selections=[]
|
|
|
|
|
]
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if (eq $in $nil) {
|
|
|
|
|
fail (printf '%s: pas de fichier avant la sélection' $e)
|
|
|
|
|
}
|
|
|
|
|
var r rc = $in[rotate] $nil
|
|
|
|
|
if (is-page-selection $e) {
|
|
|
|
|
set rc = $false
|
|
|
|
|
} elif (is-rotate-selection $e) {
|
|
|
|
|
set rc = $true
|
|
|
|
|
} else {
|
|
|
|
|
fail (printf '%s: paramètre invalide' $e)
|
|
|
|
|
}
|
|
|
|
|
if (not-eq $r $rc) {
|
|
|
|
|
if (not-eq $r $nil) {
|
|
|
|
|
set @out = $@out $in
|
|
|
|
|
set in[selections] = []
|
|
|
|
|
}
|
|
|
|
|
set in[rotate] = $rc
|
|
|
|
|
}
|
|
|
|
|
set in[selections] = [ (all $in[selections]) $e ]
|
|
|
|
|
} $selection
|
|
|
|
|
if (not-eq $in $nil) {
|
|
|
|
|
set @out = $@out $in
|
|
|
|
|
}
|
|
|
|
|
put $out
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn -t {
|
|
|
|
|
mktemp -q /tmp/qpdf_XXXXXXXXXX.pdf
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn rotate {|&empty=$false &out=$nil &keep=$false in @rotate|
|
|
|
|
|
var @args = $in
|
|
|
|
|
if (eq $out $nil) {
|
|
|
|
|
set @args = $@args --replace-input
|
|
|
|
|
} else {
|
|
|
|
|
set @args = $@args $out
|
|
|
|
|
}
|
|
|
|
|
if $empty {
|
|
|
|
|
set @args = $@args --empty
|
|
|
|
|
}
|
|
|
|
|
if $keep {
|
|
|
|
|
set @rotate = (each {|r| put --rotate=$r } $rotate)
|
|
|
|
|
qpdf $@args $@rotate
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
var tmp = []
|
|
|
|
|
try {
|
|
|
|
|
var @tmp = (each {|r|
|
|
|
|
|
var t r @s = (-t) (str:split ':' $r)
|
|
|
|
|
set s = (str:join ':' $s)
|
|
|
|
|
if (eq $s '') {
|
|
|
|
|
qpdf $in $t --rotate=$r
|
|
|
|
|
} else {
|
|
|
|
|
qpdf $in $t --pages $in $s --
|
|
|
|
|
qpdf $t --replace-input --rotate=$r
|
|
|
|
|
}
|
|
|
|
|
put $t
|
|
|
|
|
} $rotate)
|
|
|
|
|
qpdf $@args --pages $@tmp --
|
|
|
|
|
} finally {
|
|
|
|
|
rm -f $@tmp
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn -catarg {|selection|
|
|
|
|
|
var f r s = $selection[file] $selection[rotate] $selection[selections]
|
|
|
|
|
var out tmp = [] []
|
|
|
|
|
if $r {
|
|
|
|
|
var t = (-t)
|
|
|
|
|
set @tmp = $t
|
|
|
|
|
set @out = $@out $t
|
|
|
|
|
rotate &out=$t $f $@s
|
|
|
|
|
} else {
|
|
|
|
|
set @out = $@out $f
|
|
|
|
|
if (> (count $s) 0) {
|
|
|
|
|
set @out = $@out (str:join ',' $s)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
put $out $tmp
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn cat {|&empty=$false &collate=$nil &out=$nil @selection|
|
|
|
|
|
var inputs = (parse-selection $@selection)
|
|
|
|
|
var pages tmp = [] []
|
|
|
|
|
each {|in|
|
|
|
|
|
var a t = (-catarg $in)
|
|
|
|
|
set @pages = $@pages $@a
|
|
|
|
|
set @tmp = $@tmp $@t
|
|
|
|
|
} $inputs
|
|
|
|
|
try {
|
|
|
|
|
var in = $pages[0]
|
|
|
|
|
var @args = $in
|
|
|
|
|
if (eq $out $nil) {
|
|
|
|
|
set @args = $@args --replace-input
|
|
|
|
|
} else {
|
|
|
|
|
set @args = $@args $out
|
|
|
|
|
}
|
|
|
|
|
if $empty {
|
|
|
|
|
set @args = $@args --empty
|
|
|
|
|
}
|
|
|
|
|
if (bool $collate) {
|
|
|
|
|
var c = --collate
|
|
|
|
|
if (is-number $collate) {
|
|
|
|
|
set c = (str:join '=' [ $c $collate ])
|
|
|
|
|
}
|
|
|
|
|
set @args = $@args $c
|
|
|
|
|
}
|
|
|
|
|
qpdf $@args --pages $@pages --
|
|
|
|
|
} finally {
|
|
|
|
|
each {|t|
|
|
|
|
|
rm -f $t
|
|
|
|
|
} $tmp
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn decrypt {|&out=$nil in @passwd|
|
|
|
|
|
var @args = $in
|
|
|
|
|
if (eq $out $nil) {
|
|
|
|
|
set @args = $@args --replace-input
|
|
|
|
|
} else {
|
|
|
|
|
set @args = $@args $out
|
|
|
|
|
}
|
|
|
|
|
set @args = $@args --decrypt
|
|
|
|
|
if (> (count $passwd) 0) {
|
|
|
|
|
set @args = $@args $passwd[0]
|
|
|
|
|
}
|
|
|
|
|
qpdf $@args
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn -l0 {|n size|
|
|
|
|
|
set n = (to-string $n)
|
|
|
|
|
var l = (- $size (count $n))
|
|
|
|
|
str:join '' [ (repeat $l 0) $n ]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn split {|&empty=$false &size=1 in out|
|
|
|
|
|
if (not-exist $out) {
|
|
|
|
|
mkdir $out
|
|
|
|
|
}
|
|
|
|
|
var args = []
|
|
|
|
|
if $empty {
|
|
|
|
|
set @args = --empty
|
|
|
|
|
}
|
|
|
|
|
qpdf $@args --split-pages=$size $in $out'/%d.pdf'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn uncat {|&empty=$false in out @selection|
|
|
|
|
|
if (not-exist $out) {
|
|
|
|
|
mkdir $out
|
|
|
|
|
}
|
|
|
|
|
var i = 1
|
|
|
|
|
var n = (count $selection)
|
|
|
|
|
set n = (count (to-string $n))
|
|
|
|
|
each {|s|
|
|
|
|
|
cat &empty=$empty &out=$out'/'(-l0 $i $n)'.pdf' $in $s
|
|
|
|
|
set i = (+ $i 1)
|
|
|
|
|
} $selection
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn raw-stream {|in out id|
|
|
|
|
|
qpdf $in --show-object=$id --raw-stream-data > $out
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn filtered-stream {|in out id|
|
|
|
|
|
qpdf $in --show-object=$id --filtered-stream-data --normalize-content=n --stream-data=uncompress --decode-level=all > $out
|
|
|
|
|
}
|
2021-12-24 13:50:36 +00:00
|
|
|
|
|
|
|
|
|
fn attachment {|in out id|
|
|
|
|
|
qpdf $in --show-attachment=$id > $out
|
|
|
|
|
}
|