Beginning to address recryption properly
This commit is contained in:
parent
f689fa8f20
commit
88ad70ff80
100
cpdfcommand.ml
100
cpdfcommand.ml
|
@ -3,7 +3,7 @@ let demo = false
|
||||||
let noncomp = false
|
let noncomp = false
|
||||||
let major_version = 1
|
let major_version = 1
|
||||||
let minor_version = 8
|
let minor_version = 8
|
||||||
let version_date = "(unreleased, 16th September 2014)"
|
let version_date = "(unreleased, 27th October 2014)"
|
||||||
|
|
||||||
open Pdfutil
|
open Pdfutil
|
||||||
open Pdfio
|
open Pdfio
|
||||||
|
@ -355,7 +355,8 @@ type args =
|
||||||
mutable original_filename : string;
|
mutable original_filename : string;
|
||||||
mutable was_encrypted : bool;
|
mutable was_encrypted : bool;
|
||||||
mutable cpdflin : string option;
|
mutable cpdflin : string option;
|
||||||
mutable recrypt : bool}
|
mutable recrypt : bool;
|
||||||
|
mutable was_decrypted_with_owner : bool}
|
||||||
|
|
||||||
(* List of all filenames in any AND stage - this is used to check that we don't
|
(* List of all filenames in any AND stage - this is used to check that we don't
|
||||||
overwrite any input file when -dont-overwrite-existing-files is used. *)
|
overwrite any input file when -dont-overwrite-existing-files is used. *)
|
||||||
|
@ -436,7 +437,8 @@ let args =
|
||||||
original_filename = "";
|
original_filename = "";
|
||||||
was_encrypted = false;
|
was_encrypted = false;
|
||||||
cpdflin = None;
|
cpdflin = None;
|
||||||
recrypt = false}
|
recrypt = false;
|
||||||
|
was_decrypted_with_owner = false}
|
||||||
|
|
||||||
let reset_arguments () =
|
let reset_arguments () =
|
||||||
args.op <- None;
|
args.op <- None;
|
||||||
|
@ -508,9 +510,25 @@ let reset_arguments () =
|
||||||
args.labelstyle <- Pdfpagelabels.DecimalArabic;
|
args.labelstyle <- Pdfpagelabels.DecimalArabic;
|
||||||
args.labelprefix <- None;
|
args.labelprefix <- None;
|
||||||
args.labelstartval <- 1;
|
args.labelstartval <- 1;
|
||||||
args.squeeze <- false;
|
args.squeeze <- false
|
||||||
args.recrypt <- false
|
(* Do not reset original_filename or cpdflin or was_encrypted or
|
||||||
(* Do not reset original_filename or cpdflin or was_encrypted, since we want it to work across ANDs. *)
|
* was_decrypted_with_owner or recrypt, since we want it to work across ANDs. *)
|
||||||
|
|
||||||
|
let string_of_permission = function
|
||||||
|
| Pdfcrypt.NoEdit -> "No edit"
|
||||||
|
| Pdfcrypt.NoPrint -> "No print"
|
||||||
|
| Pdfcrypt.NoCopy -> "No copy"
|
||||||
|
| Pdfcrypt.NoAnnot -> "No annotate"
|
||||||
|
| Pdfcrypt.NoForms -> "No edit forms"
|
||||||
|
| Pdfcrypt.NoExtract -> "No extract"
|
||||||
|
| Pdfcrypt.NoAssemble -> "No assemble"
|
||||||
|
| Pdfcrypt.NoHqPrint -> "No high-quality print"
|
||||||
|
|
||||||
|
let getpermissions pdf =
|
||||||
|
fold_left
|
||||||
|
(fun x y -> if x = "" then x ^ y else x ^ ", " ^ y)
|
||||||
|
""
|
||||||
|
(map string_of_permission (Pdfread.permissions pdf))
|
||||||
|
|
||||||
let banlist_of_args () =
|
let banlist_of_args () =
|
||||||
let l = ref [] in
|
let l = ref [] in
|
||||||
|
@ -532,14 +550,31 @@ performed is checked to see if it's allowable under the permissions regime. *)
|
||||||
bans list in the input file, the operation cannot proceed. Other operations
|
bans list in the input file, the operation cannot proceed. Other operations
|
||||||
cannot proceed at all without owner password. *)
|
cannot proceed at all without owner password. *)
|
||||||
let banned banlist = function
|
let banned banlist = function
|
||||||
| Fonts | Info | Metadata | PageInfo | CountPages -> false (* Always allowed *)
|
| Fonts | Info | Metadata | PageInfo | CountPages
|
||||||
|
| ListAttachedFiles | ListAnnotationsMore | ListAnnotations
|
||||||
|
| ListBookmarks | ImageResolution _ | MissingFonts
|
||||||
|
| PrintPageLabels | Clean | Compress | Decompress
|
||||||
|
| RemoveUnusedResources -> false (* Always allowed *)
|
||||||
| Decrypt | Encrypt -> true (* Never allowed *)
|
| Decrypt | Encrypt -> true (* Never allowed *)
|
||||||
|
| ExtractText | ExtractImages | ExtractFontFile -> mem Pdfcrypt.NoExtract banlist
|
||||||
|
| AddBookmarks _ | PadBefore | PadAfter | PadEvery _ | PadMultiple _
|
||||||
|
| Merge | Split | SplitOnBookmarks _ | RotateContents _ | Rotate _
|
||||||
|
| Rotateby _ | Upright | VFlip | HFlip | SetPageLayout _
|
||||||
|
| SetPageMode _ | HideToolbar _ | HideMenubar _ | HideWindowUI _
|
||||||
|
| FitWindow _ | CenterWindow _ | DisplayDocTitle _ | ChangeId
|
||||||
|
| RemoveId | CopyId _ | OpenAtPageFit _ | OpenAtPage _
|
||||||
|
| AddPageLabels | RemovePageLabels -> mem Pdfcrypt.NoAssemble banlist
|
||||||
| _ -> mem Pdfcrypt.NoEdit banlist
|
| _ -> mem Pdfcrypt.NoEdit banlist
|
||||||
|
|
||||||
let operation_allowed banlist op =
|
let operation_allowed pdf banlist op =
|
||||||
match op with
|
match op with
|
||||||
| None -> true (* Merge *) (* changed to allow it *)
|
| None ->
|
||||||
| Some op -> not (banned banlist op)
|
Printf.printf "operation is None, so allowed!\n";
|
||||||
|
true (* Merge *) (* changed to allow it *)
|
||||||
|
| Some op ->
|
||||||
|
if args.debugcrypt then Printf.printf "operation_allowed: op = %s\n" (string_of_op op);
|
||||||
|
if args.debugcrypt then Printf.printf "Permissions: %s\n" (getpermissions pdf);
|
||||||
|
not (banned banlist op)
|
||||||
|
|
||||||
let rec decrypt_if_necessary (_, _, _, user_pw, owner_pw) op pdf =
|
let rec decrypt_if_necessary (_, _, _, user_pw, owner_pw) op pdf =
|
||||||
if args.debugcrypt then
|
if args.debugcrypt then
|
||||||
|
@ -550,13 +585,15 @@ let rec decrypt_if_necessary (_, _, _, user_pw, owner_pw) op pdf =
|
||||||
if not (Pdfcrypt.is_encrypted pdf) then pdf else
|
if not (Pdfcrypt.is_encrypted pdf) then pdf else
|
||||||
match Pdfcrypt.decrypt_pdf_owner owner_pw pdf with
|
match Pdfcrypt.decrypt_pdf_owner owner_pw pdf with
|
||||||
| Some pdf ->
|
| Some pdf ->
|
||||||
if args.debugcrypt then Printf.printf "Managed to decrypt with owner password\n"; pdf
|
args.was_decrypted_with_owner <- true;
|
||||||
|
if args.debugcrypt then Printf.printf "Managed to decrypt with owner password\n";
|
||||||
|
pdf
|
||||||
| _ ->
|
| _ ->
|
||||||
if args.debugcrypt then Printf.printf "Couldn't decrypt with owner password %s\n" owner_pw;
|
if args.debugcrypt then Printf.printf "Couldn't decrypt with owner password %s\n" owner_pw;
|
||||||
match Pdfcrypt.decrypt_pdf user_pw pdf with
|
match Pdfcrypt.decrypt_pdf user_pw pdf with
|
||||||
| Some pdf, permissions ->
|
| Some pdf, permissions ->
|
||||||
if args.debugcrypt then Printf.printf "Managed to decrypt with user password\n";
|
if args.debugcrypt then Printf.printf "Managed to decrypt with user password\n";
|
||||||
if operation_allowed permissions op
|
if operation_allowed pdf permissions op
|
||||||
then pdf
|
then pdf
|
||||||
else soft_error "User password cannot give permission for this operation"
|
else soft_error "User password cannot give permission for this operation"
|
||||||
| _ ->
|
| _ ->
|
||||||
|
@ -1851,7 +1888,9 @@ let get_pdf_from_input_kind ((_, _, _, u, o) as input) op = function
|
||||||
end;
|
end;
|
||||||
begin try Hashtbl.find filenames s with
|
begin try Hashtbl.find filenames s with
|
||||||
Not_found ->
|
Not_found ->
|
||||||
let pdf = decrypt_if_necessary input op (pdfread_pdf_of_file (optstring u) (optstring o) s) in
|
let pdf = pdfread_pdf_of_file (optstring u) (optstring o) s in
|
||||||
|
args.was_encrypted <- Pdfcrypt.is_encrypted pdf;
|
||||||
|
let pdf = decrypt_if_necessary input op pdf in
|
||||||
Hashtbl.add filenames s pdf; pdf
|
Hashtbl.add filenames s pdf; pdf
|
||||||
end
|
end
|
||||||
| StdIn ->
|
| StdIn ->
|
||||||
|
@ -1891,11 +1930,14 @@ let get_single_pdf_nodecrypt read_lazy =
|
||||||
raise (Arg.Bad "cpdf: No input specified.\n")
|
raise (Arg.Bad "cpdf: No input specified.\n")
|
||||||
|
|
||||||
let really_write_pdf ?(encryption = None) mk_id pdf outname =
|
let really_write_pdf ?(encryption = None) mk_id pdf outname =
|
||||||
|
if args.debugcrypt then Printf.printf "really_write_pdf\n";
|
||||||
let outname' =
|
let outname' =
|
||||||
if args.linearize
|
if args.linearize
|
||||||
then Filename.temp_file "cpdflin" ".pdf"
|
then Filename.temp_file "cpdflin" ".pdf"
|
||||||
else outname
|
else outname
|
||||||
in
|
in
|
||||||
|
if args.debugcrypt then
|
||||||
|
Printf.printf "args.recrypt = %b, args.was_encrypted = %b\n" args.recrypt args.was_encrypted;
|
||||||
begin
|
begin
|
||||||
if args.recrypt && args.was_encrypted then
|
if args.recrypt && args.was_encrypted then
|
||||||
begin
|
begin
|
||||||
|
@ -1904,6 +1946,8 @@ let really_write_pdf ?(encryption = None) mk_id pdf outname =
|
||||||
(get_single_pdf_nodecrypt false) pdf args.user outname'
|
(get_single_pdf_nodecrypt false) pdf args.user outname'
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
begin
|
||||||
|
if not args.was_encrypted || args.was_decrypted_with_owner && args.was_encrypted then
|
||||||
begin
|
begin
|
||||||
if args.debugcrypt then Printf.printf "Pdf to file in really_write_pdf\n";
|
if args.debugcrypt then Printf.printf "Pdf to file in really_write_pdf\n";
|
||||||
Pdfwrite.pdf_to_file_options
|
Pdfwrite.pdf_to_file_options
|
||||||
|
@ -1911,6 +1955,9 @@ let really_write_pdf ?(encryption = None) mk_id pdf outname =
|
||||||
~generate_objstm:args.create_objstm
|
~generate_objstm:args.create_objstm
|
||||||
false encryption mk_id pdf outname'
|
false encryption mk_id pdf outname'
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
soft_error "You must supply -recrypt here, or provide the owner password."
|
||||||
|
end
|
||||||
end;
|
end;
|
||||||
begin
|
begin
|
||||||
if args.linearize then
|
if args.linearize then
|
||||||
|
@ -1936,6 +1983,7 @@ let really_write_pdf ?(encryption = None) mk_id pdf outname =
|
||||||
((float s /. float !initial_file_size) *. 100.)
|
((float s /. float !initial_file_size) *. 100.)
|
||||||
|
|
||||||
let write_pdf ?(encryption = None) ?(is_decompress=false) mk_id pdf =
|
let write_pdf ?(encryption = None) ?(is_decompress=false) mk_id pdf =
|
||||||
|
if args.debugcrypt then Printf.printf "write_pdf\n";
|
||||||
if args.create_objstm && not args.keepversion
|
if args.create_objstm && not args.keepversion
|
||||||
then pdf.Pdf.minor <- max pdf.Pdf.minor 5;
|
then pdf.Pdf.minor <- max pdf.Pdf.minor 5;
|
||||||
let mk_id = args.makenewid || mk_id in
|
let mk_id = args.makenewid || mk_id in
|
||||||
|
@ -2138,21 +2186,6 @@ let getencryption pdf =
|
||||||
| Some (Pdfwrite.AES256bitISO true) -> "256bit AES ISO, Metadata encrypted"
|
| Some (Pdfwrite.AES256bitISO true) -> "256bit AES ISO, Metadata encrypted"
|
||||||
| Some (Pdfwrite.AES256bitISO false) -> "256bit AES ISO, Metadata not encrypted"
|
| Some (Pdfwrite.AES256bitISO false) -> "256bit AES ISO, Metadata not encrypted"
|
||||||
|
|
||||||
let string_of_permission = function
|
|
||||||
| Pdfcrypt.NoEdit -> "No edit"
|
|
||||||
| Pdfcrypt.NoPrint -> "No print"
|
|
||||||
| Pdfcrypt.NoCopy -> "No copy"
|
|
||||||
| Pdfcrypt.NoAnnot -> "No Annotate"
|
|
||||||
| Pdfcrypt.NoForms -> "No edit forms"
|
|
||||||
| Pdfcrypt.NoExtract -> "No extract"
|
|
||||||
| Pdfcrypt.NoAssemble -> "No assemble"
|
|
||||||
| Pdfcrypt.NoHqPrint -> "No high-quality print"
|
|
||||||
|
|
||||||
let getpermissions pdf =
|
|
||||||
fold_left
|
|
||||||
(fun x y -> if x = "" then x ^ y else x ^ ", " ^ y)
|
|
||||||
""
|
|
||||||
(map string_of_permission (Pdfread.permissions pdf))
|
|
||||||
|
|
||||||
(* If a cropbox exists, make it the mediabox. If not, change nothing. *)
|
(* If a cropbox exists, make it the mediabox. If not, change nothing. *)
|
||||||
let copy_cropbox_to_mediabox pdf range =
|
let copy_cropbox_to_mediabox pdf range =
|
||||||
|
@ -2707,17 +2740,12 @@ let go () =
|
||||||
in
|
in
|
||||||
match namewiths with
|
match namewiths with
|
||||||
| (namewiths, _, _, _, _) as input::t ->
|
| (namewiths, _, _, _, _) as input::t ->
|
||||||
let spdf =
|
let spdf = get_pdf_from_input_kind input (Some Merge) namewiths in
|
||||||
get_pdf_from_input_kind
|
|
||||||
input
|
|
||||||
(Some Decrypt)
|
|
||||||
namewiths
|
|
||||||
in
|
|
||||||
write_pdf x (Cpdf.copy_id true spdf pdf)
|
write_pdf x (Cpdf.copy_id true spdf pdf)
|
||||||
| _ -> write_pdf x pdf
|
| _ -> write_pdf x pdf
|
||||||
in
|
in
|
||||||
let names, ranges, rotations, _, _ = split5 inputs in
|
let names, ranges, rotations, _, _ = split5 inputs in
|
||||||
let pdfs = map2 (fun i -> get_pdf_from_input_kind i (Some Decrypt)) inputs names in
|
let pdfs = map2 (fun i -> get_pdf_from_input_kind i (Some Merge)) inputs names in
|
||||||
(* If at least one file had object streams and args.preserve_objstm is true, set -objstm-create *)
|
(* If at least one file had object streams and args.preserve_objstm is true, set -objstm-create *)
|
||||||
if args.preserve_objstm then
|
if args.preserve_objstm then
|
||||||
iter
|
iter
|
||||||
|
@ -2805,7 +2833,7 @@ let go () =
|
||||||
| (AlreadyInMemory pdf, _, _, _, _) as input::_ -> pdf, "", input
|
| (AlreadyInMemory pdf, _, _, _, _) as input::_ -> pdf, "", input
|
||||||
| _ -> raise (Arg.Bad "cpdf: No input specified.\n")
|
| _ -> raise (Arg.Bad "cpdf: No input specified.\n")
|
||||||
in
|
in
|
||||||
let pdf = decrypt_if_necessary input (Some Info) pdf in
|
let pdf = decrypt_if_necessary input (Some CountPages) pdf in
|
||||||
output_page_count pdf
|
output_page_count pdf
|
||||||
| Some Clean ->
|
| Some Clean ->
|
||||||
begin match args.out with
|
begin match args.out with
|
||||||
|
|
Loading…
Reference in New Issue