diff --git a/cpdfcommand.ml b/cpdfcommand.ml index 5efe50b..97f03e7 100644 --- a/cpdfcommand.ml +++ b/cpdfcommand.ml @@ -3471,19 +3471,41 @@ let go () = | (AlreadyInMemory pdf, _, _, _, _, _) as input::_ -> pdf, "", input | _ -> raise (Arg.Bad "cpdf: No input specified.\n") in - Printf.printf "Encryption: %s\n" (getencryption pdf); - Printf.printf "Permissions: %s\n" (getpermissions pdf); + let json = ref [] in + if args.format_json + then json =| ("Encryption", `String (getencryption pdf)) + else Printf.printf "Encryption: %s\n" (getencryption pdf); + if args.format_json + then json =| ("Permissions", `List (map (fun p -> `String (string_of_permission p)) (Pdfread.permissions pdf))) + else Printf.printf "Permissions: %s\n" (getpermissions pdf); if inname <> "" then - Printf.printf "Linearized: %b\n" (Pdfread.is_linearized (Pdfio.input_of_channel (open_in_bin inname))); - Printf.printf "Object streams: %b\n" (length (list_of_hashtbl pdf.Pdf.objects.Pdf.object_stream_ids) > 0); - Printf.printf "ID: %s\n" - (match - Pdf.lookup_direct pdf "/ID" pdf.Pdf.trailerdict with - | Some (Pdf.Array [Pdf.String s; Pdf.String s']) -> Printf.sprintf "%s %s" (Pdfwrite.make_hex_pdf_string s) (Pdfwrite.make_hex_pdf_string s'); - | _ -> "None"); + let lin = Pdfread.is_linearized (Pdfio.input_of_channel (open_in_bin inname)) in + if args.format_json then + json =| ("Linearized", `Bool lin) else Printf.printf "Linearized: %b\n" lin; + let objstm = length (list_of_hashtbl pdf.Pdf.objects.Pdf.object_stream_ids) > 0 in + if args.format_json + then json =| ("Object streams", `Bool objstm) + else Printf.printf "Object streams: %b\n" objstm; + let ida, idb = + match Pdf.lookup_direct pdf "/ID" pdf.Pdf.trailerdict with + | Some (Pdf.Array [Pdf.String s; Pdf.String s']) -> + (Pdfwrite.make_hex_pdf_string s, Pdfwrite.make_hex_pdf_string s') + | _ -> "", "" + in + let fixid s = implode (rev (tl (rev (tl (explode s))))) in + if args.format_json + then json =| ("ID", if ida ^ idb = "" then `Null else `List [`String (fixid ida); `String (fixid idb)]) + else (if ida ^ idb = "" then Printf.printf "ID: None" else Printf.printf "ID: %s %s\n" ida idb); let pdf = decrypt_if_necessary input (Some Info) pdf in - Cpdfmetadata.output_info args.encoding pdf; - Cpdfmetadata.output_xmp_info args.encoding pdf + if args.format_json then + Cpdfmetadata.output_info ~json Cpdfmetadata.UTF8 pdf; + Cpdfmetadata.output_xmp_info ~json Cpdfmetadata.UTF8 pdf; + flprint (Cpdfyojson.Safe.pretty_to_string (`Assoc (rev !json))) + else + begin + Cpdfmetadata.output_info args.encoding pdf; + Cpdfmetadata.output_xmp_info args.encoding pdf + end | Some PageInfo -> begin match args.inputs, args.out with | (_, pagespec, _, _, _, _)::_, _ -> diff --git a/cpdfmetadata.ml b/cpdfmetadata.ml index db23f9a..f8e5a65 100644 --- a/cpdfmetadata.ml +++ b/cpdfmetadata.ml @@ -188,28 +188,49 @@ let get_viewer_pref_item name pdf = end | _ -> "" -let output_info encoding pdf = +let output_info ?(json=ref [("none", `Null)]) encoding pdf = + let notjson = !json = [("none", `Null)] in let getstring = getstring encoding pdf in - Printf.printf "Version: %i.%i\n" pdf.Pdf.major pdf.Pdf.minor; - Printf.printf "Pages: %i\n" (Pdfpage.endpage pdf); - Printf.printf "Title: %s\n" (getstring "/Title"); - Printf.printf "Author: %s\n" (getstring "/Author"); - Printf.printf "Subject: %s\n" (getstring "/Subject"); - Printf.printf "Keywords: %s\n" (getstring "/Keywords"); - Printf.printf "Creator: %s\n" (getstring "/Creator"); - Printf.printf "Producer: %s\n" (getstring "/Producer"); - Printf.printf "Created: %s\n" (getstring "/CreationDate"); - Printf.printf "Modified: %s\n" (getstring "/ModDate"); - Printf.printf "Trapped: %s\n" (getstring "/Trapped"); - Printf.printf "PageMode: %s\n" (get_catalog_item "/PageMode" pdf); - Printf.printf "PageLayout: %s\n" (get_catalog_item "/PageLayout" pdf); - Printf.printf "HideToolbar: %s\n" (get_viewer_pref_item "/HideToolbar" pdf); - Printf.printf "HideMenubar: %s\n" (get_viewer_pref_item "/HideMenubar" pdf); - Printf.printf "HideWindowUI: %s\n" (get_viewer_pref_item "/HideWindowUI" pdf); - Printf.printf "FitWindow: %s\n" (get_viewer_pref_item "/FitWindow" pdf); - Printf.printf "CenterWindow: %s\n" (get_viewer_pref_item "/CenterWindow" pdf); - Printf.printf "DisplayDocTitle: %s\n" (get_viewer_pref_item "/DisplayDocTitle" pdf); - Printf.printf "NonFullScreenPageMode: %s\n" (get_viewer_pref_item "/NonFullScreenPageMode" pdf); + if notjson then Printf.printf "Version: %i.%i\n" pdf.Pdf.major pdf.Pdf.minor; + json =| ("Version", `List [`Int pdf.Pdf.major; `Int pdf.Pdf.minor]); + if notjson then Printf.printf "Pages: %i\n" (Pdfpage.endpage pdf); + json =| ("Pages", `Int (Pdfpage.endpage pdf)); + if notjson then Printf.printf "Title: %s\n" (getstring "/Title"); + json =| ("Title", `String (getstring "/Title")); + if notjson then Printf.printf "Author: %s\n" (getstring "/Author"); + json =| ("Author", `String (getstring "/Author")); + if notjson then Printf.printf "Subject: %s\n" (getstring "/Subject"); + json =| ("Subject", `String (getstring "/Subject")); + if notjson then Printf.printf "Keywords: %s\n" (getstring "/Keywords"); + json =| ("Keywords", `String (getstring "/Keywords")); + if notjson then Printf.printf "Creator: %s\n" (getstring "/Creator"); + json =| ("Creator", `String (getstring "/Creator")); + if notjson then Printf.printf "Producer: %s\n" (getstring "/Producer"); + json =| ("Producer", `String (getstring "/Producer")); + if notjson then Printf.printf "Created: %s\n" (getstring "/CreationDate"); + json =| ("Created", `String (getstring "/CreationDate")); + if notjson then Printf.printf "Modified: %s\n" (getstring "/ModDate"); + json =| ("Modified", `String (getstring "/ModDate")); + if notjson then Printf.printf "Trapped: %s\n" (getstring "/Trapped"); + json =| ("Trapped", `Bool (bool_of_string (String.lowercase_ascii (getstring "/Trapped")))); + if notjson then Printf.printf "PageMode: %s\n" (get_catalog_item "/PageMode" pdf); + json =| ("PageMode", match (get_catalog_item "/PageMode" pdf) with "" -> `Null | x -> `String x); + if notjson then Printf.printf "PageLayout: %s\n" (get_catalog_item "/PageLayout" pdf); + json =| ("PageLayout", match (get_catalog_item "/PageLayout" pdf) with "" -> `Null | x -> `String x); + if notjson then Printf.printf "HideToolbar: %s\n" (get_viewer_pref_item "/HideToolbar" pdf); + json =| ("HideToolbar", match get_viewer_pref_item "/HideToolbar" pdf with "" -> `Null | s -> `Bool (bool_of_string s)); + if notjson then Printf.printf "HideMenubar: %s\n" (get_viewer_pref_item "/HideMenubar" pdf); + json =| ("HideMenubar", match get_viewer_pref_item "/HideMenubar" pdf with "" -> `Null | s -> `Bool (bool_of_string s)); + if notjson then Printf.printf "HideWindowUI: %s\n" (get_viewer_pref_item "/HideWindowUI" pdf); + json =| ("HideWindowUI", match get_viewer_pref_item "/HideWindowUI" pdf with "" -> `Null | s -> `Bool (bool_of_string s)); + if notjson then Printf.printf "FitWindow: %s\n" (get_viewer_pref_item "/FitWindow" pdf); + json =| ("FitWindow", match get_viewer_pref_item "/FitWindow" pdf with "" -> `Null | s -> `Bool (bool_of_string s)); + if notjson then Printf.printf "CenterWindow: %s\n" (get_viewer_pref_item "/CenterWindow" pdf); + json =| ("CenterWindow", match get_viewer_pref_item "/CenterWindow" pdf with "" -> `Null | s -> `Bool (bool_of_string s)); + if notjson then Printf.printf "DisplayDocTitle: %s\n" (get_viewer_pref_item "/DisplayDocTitle" pdf); + json =| ("DisplayDocTitle", match get_viewer_pref_item "/DisplayDocTitle" pdf with "" -> `Null | s -> `Bool (bool_of_string s)); + if notjson then Printf.printf "NonFullScreenPageMode: %s\n" (get_viewer_pref_item "/NonFullScreenPageMode" pdf); + json =| ("NonFullPageScreenMode", match (get_viewer_pref_item "/NonFullPageScreenMode" pdf) with "" -> `Null | x -> `String x); type xmltree = E of Cpdfxmlm.tag * xmltree list @@ -298,13 +319,19 @@ let rec get_data_for namespace name = function x :: _ -> Some x | _ -> None -let output_xmp_info encoding pdf = +let output_xmp_info ?(json=ref [("none", `Null)]) encoding pdf = + let notjson = !json = [("none", `Null)] in let print_out tree title namespace name = match get_data_for namespace name tree with None -> () | Some data -> - Printf.printf "%s: " title; - print_endline data + if notjson then + begin + Printf.printf "%s: " title; + print_endline data + end + else + json =| (title, `String data) in match get_metadata pdf with None -> () diff --git a/cpdfmetadata.mli b/cpdfmetadata.mli index 0033c75..20713c6 100644 --- a/cpdfmetadata.mli +++ b/cpdfmetadata.mli @@ -49,10 +49,10 @@ from the /Info dictionary, returning it as a UTF8 string *) val get_info_utf8 : Pdf.t -> string -> string (** Output to standard output general information about a PDF. *) -val output_info : encoding -> Pdf.t -> unit +val output_info : ?json:(string * Cpdfyojson.Safe.t) list ref -> encoding -> Pdf.t -> unit (** Output to standard output information from any XMP metadata stream in a PDF. *) -val output_xmp_info : encoding -> Pdf.t -> unit +val output_xmp_info : ?json:(string * Cpdfyojson.Safe.t) list ref -> encoding -> Pdf.t -> unit (** Create XMP metadata from scratch *) val create_metadata : Pdf.t -> Pdf.t