diff --git a/Makefile b/Makefile index 08452c6..955dd6c 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # Build the cpdf command line tools and top level MODS = cpdfstream tjutil tjutf16 tjllist tjparsermonad tjjson \ - xmlm cpdfjson cpdfstrftime cpdfcoord \ + xmlm cpdferror cpdfjson cpdfstrftime cpdfcoord cpdfattach \ cpdfpagespec cpdfposition cpdf cpdfcommand SOURCES = $(foreach x,$(MODS),$(x).ml $(x).mli) cpdfcommandrun.ml diff --git a/cpdf.ml b/cpdf.ml index f398288..97ce76e 100644 --- a/cpdf.ml +++ b/cpdf.ml @@ -1,6 +1,7 @@ (* CPDF Core routines *) open Pdfutil open Pdfio +open Cpdferror let debug = ref false @@ -434,12 +435,6 @@ let protect fast pdf resources content = let qs = addstream (many Pdfops.Op_Q deficit @ [Pdfops.Op_Q]) in [Pdf.Indirect q] @ content @ [Pdf.Indirect qs] -exception SoftError of string - -let error s = raise (SoftError s) - -exception HardError of string - (* Union two resource dictionaries from the same PDF. *) let combine_pdf_resources pdf a b = let a_entries = @@ -532,228 +527,6 @@ let presentation range t d h i dir effect_dur pdf = in Pdfpage.change_pages true pdf pages' -(* Attaching files *) -let attach_file ?memory keepversion topage pdf file = - let data = - match memory with - Some data -> data - | None -> - let ch = open_in_bin file in - let len = in_channel_length ch in - let stream = mkbytes len in - let i = input_of_channel ch in - setinit i stream 0 len; - close_in ch; - stream - in - let filestream = - Pdf.Stream - (ref (Pdf.Dictionary - [("/Length", Pdf.Integer (bytes_size data)); - ("/Type", Pdf.Name "/EmbeddedFile"); - ("/Params", - Pdf.Dictionary - [("/Size", Pdf.Integer (bytes_size data)); - ("/CheckSum", Pdf.String (Digest.string (string_of_bytes data))) - ])], - Pdf.Got data)) - in - let filestream_num = Pdf.addobj pdf filestream in - let basename = Pdftext.pdfdocstring_of_utf8 (Filename.basename file) in - let filespec = - Pdf.Dictionary - [("/EF", Pdf.Dictionary ["/F", Pdf.Indirect filestream_num]); - ("/F", Pdf.String basename); - ("/Type", Pdf.Name "/Filespec"); - ("/Desc", Pdf.String ""); - ("/UF", Pdf.String basename)] - in - match topage with - | None -> - (* Look up /Names and /EmbeddedFiles and /Names. *) - let rootdict = Pdf.lookup_obj pdf pdf.Pdf.root in - let namedict = - match Pdf.lookup_direct pdf "/Names" rootdict with - | None -> Pdf.Dictionary [] - | Some namedict -> namedict - in - let embeddednamedict = - match Pdf.lookup_direct pdf "/EmbeddedFiles" namedict with - | None -> Pdf.Dictionary [] - | Some embeddednamedict -> embeddednamedict - in - let elts = - match Pdf.lookup_direct pdf "/Names" embeddednamedict with - | Some (Pdf.Array elts) -> elts - | _ -> [] - in - let filespecobj = Pdf.addobj pdf filespec in - let names' = Pdf.Array (elts @ [Pdf.String basename; Pdf.Indirect filespecobj]) in - let embeddednamedict' = Pdf.add_dict_entry embeddednamedict "/Names" names' in - let namedict' = Pdf.add_dict_entry namedict "/EmbeddedFiles" embeddednamedict' in - let rootdict' = Pdf.add_dict_entry rootdict "/Names" namedict' in - let rootnum = Pdf.addobj pdf rootdict' in - {pdf with - Pdf.minor = if keepversion then pdf.Pdf.minor else max pdf.Pdf.minor 4; - Pdf.root = rootnum; - Pdf.trailerdict = - Pdf.add_dict_entry - pdf.Pdf.trailerdict "/Root" (Pdf.Indirect rootnum)} - | Some pagenumber -> - let pages = Pdfpage.pages_of_pagetree pdf in - if pagenumber < 0 || pagenumber > length pages then error "attach_file: Page not found" else - let page = select pagenumber pages in - let annots = - match Pdf.lookup_direct pdf "/Annots" page.Pdfpage.rest with - | Some (Pdf.Array annots) -> annots - | _ -> [] - in - let rect = - let minx, miny, maxx, maxy = Pdf.parse_rectangle page.Pdfpage.mediabox in - Pdf.Array [Pdf.Real 18.; Pdf.Real (maxy -. 45.); Pdf.Real 45.; Pdf.Real (maxy -. 18.)] - in - let filespecobj = Pdf.addobj pdf filespec in - let annot = - Pdf.Dictionary - [("/FS", Pdf.Indirect filespecobj); - ("/Subtype", Pdf.Name "/FileAttachment"); - ("/Contents", Pdf.String basename); - ("/Rect", rect)] - in - let annots' = Pdf.Array (annot::annots) in - let page' = - {page with Pdfpage.rest = Pdf.add_dict_entry page.Pdfpage.rest "/Annots" annots'} - in - let pages' = replace_number pagenumber page' pages in - let pdf = Pdfpage.change_pages true pdf pages' in - {pdf with - Pdf.minor = if keepversion then pdf.Pdf.minor else max pdf.Pdf.minor 4} - -type attachment = - {name : string; - pagenumber : int; - data : unit -> Pdfio.bytes} - -let list_attached_files pdf = - let toplevel = - match Pdf.lookup_direct pdf "/Root" pdf.Pdf.trailerdict with - | None -> [] - | Some rootdict -> - match Pdf.lookup_direct pdf "/Names" rootdict with - | None -> [] - | Some namedict -> - match Pdf.lookup_direct pdf "/EmbeddedFiles" namedict with - | Some nametree -> - map - (function (x, ef) -> - match Pdf.lookup_direct pdf "/EF" ef with - | Some ((Pdf.Dictionary _) as d) -> - begin match Pdf.lookup_direct pdf "/F" d with - | Some stream -> - {name = x; - pagenumber = 0; - data = - (fun () -> - try - Pdf.getstream stream; - Pdfcodec.decode_pdfstream pdf stream; - match stream with - Pdf.Stream {contents = (_, Pdf.Got data)} -> data - | _ -> raise Not_found - with - _ -> raise (Pdf.PDFError "could not retreive attachment data"))} - | None -> raise (Pdf.PDFError "/F not found") - end - | _ -> raise (Pdf.PDFError "/EF not found")) - (option_map - (function (Pdf.String s, ef) -> Some (s, ef) | _ -> None) - (Pdf.contents_of_nametree pdf nametree)) - | _ -> [] - in let pagelevel = - let pages = Pdfpage.pages_of_pagetree pdf in - flatten - (map2 - (fun page pagenumber -> - option_map - (function annot -> - match Pdf.lookup_direct pdf "/Subtype" annot with - | Some (Pdf.Name "/FileAttachment") -> - (match Pdf.lookup_direct pdf "/Contents" annot with - | Some (Pdf.String s) -> - begin match Pdf.lookup_direct pdf "/FS" annot with - | Some ((Pdf.Dictionary _) as d) -> - (*Printf.eprintf "%s\n%!" (Pdfwrite.string_of_pdf d);*) - begin match Pdf.lookup_direct pdf "/EF" d with - | Some ((Pdf.Dictionary _) as d) -> - begin match Pdf.lookup_direct pdf "/F" d with - | Some stream -> - Some - {name = s; - pagenumber = pagenumber; - data = - (fun () -> - try - Pdf.getstream stream; - Pdfcodec.decode_pdfstream pdf stream; - match stream with - Pdf.Stream {contents = (_, Pdf.Got data)} -> data - | _ -> raise Not_found - with - _ -> raise (Pdf.PDFError "could not retreive attachment data"))} - | _ -> raise (Pdf.PDFError "no /F found in attachment") - end - | _ -> - Some - {name = s; - pagenumber = pagenumber; - data = (fun () -> raise (Pdf.PDFError "no attachment data"))} - end - | _ -> None - end - | _ -> None) - | _ -> None) - (match Pdf.lookup_direct pdf "/Annots" page.Pdfpage.rest with - | Some (Pdf.Array annots) -> annots - | _ -> [])) - pages - (indx pages)) - in - toplevel @ pagelevel - -(* \section{Remove Attached files} *) -let remove_attached_files_on_pages pdf = - let remove_from_page page = - {page with Pdfpage.rest = - Pdf.add_dict_entry page.Pdfpage.rest "/Annots" - (Pdf.Array - (option_map - (function annot -> - match Pdf.lookup_direct pdf "/Subtype" annot with - | Some (Pdf.Name "/FileAttachment") -> None - | _ -> Some annot) - (match Pdf.lookup_direct pdf "/Annots" page.Pdfpage.rest with - | Some (Pdf.Array annots) -> annots - | _ -> [])))} - in - Pdfpage.change_pages true pdf (map remove_from_page (Pdfpage.pages_of_pagetree pdf)) - -let remove_attached_files pdf = - let pdf = remove_attached_files_on_pages pdf in - match Pdf.lookup_direct pdf "/Root" pdf.Pdf.trailerdict with - | None -> pdf - | Some rootdict -> - match Pdf.lookup_direct pdf "/Names" rootdict with - | None -> pdf - | Some namedict -> - let namedict' = Pdf.remove_dict_entry namedict "/EmbeddedFiles" in - let rootdict' = Pdf.add_dict_entry rootdict "/Names" namedict' in - let rootdict'num = Pdf.addobj pdf rootdict' in - {pdf with - Pdf.root = - rootdict'num; - Pdf.trailerdict = - Pdf.add_dict_entry pdf.Pdf.trailerdict "/Root" (Pdf.Indirect rootdict'num)} - (* \section{Copy an /ID from one file to another} *) let copy_id keepversion copyfrom copyto = match Pdf.lookup_direct copyfrom "/ID" copyfrom.Pdf.trailerdict with diff --git a/cpdf.mli b/cpdf.mli index 027cc18..cf0002c 100644 --- a/cpdf.mli +++ b/cpdf.mli @@ -9,11 +9,6 @@ all - the PDF string is output as-is. [UTF8] converts loslessly to UTF8. correspond to 7 bit ASCII. *) type encoding = Raw | UTF8 | Stripped -exception SoftError of string -exception HardError of string -(** Two exceptions recommended for use with the library, though currently not -raised by any function in this module. Cpdfcommand uses them extensively. *) - (** {2 Debug} *) (** Debug: Print out a PDF in readable form to the terminal *) @@ -91,21 +86,6 @@ adds a presentation on the pages in [range]. See cpdfmanual.pdf for details. val presentation : int list -> string option -> float option -> bool -> bool -> int -> float -> Pdf.t -> Pdf.t -(** {2 File Attachments} *) -(** [attach_file keepversion topage pdf filename] attaches the file in [filename] to the pdf, optionally to a page (rather than document-level). If keepversion is true, the PDF version number won't be altered. *) -val attach_file : ?memory:Pdfio.bytes -> bool -> int option -> Pdf.t -> string -> Pdf.t - -(** Remove attached files. *) -val remove_attached_files : Pdf.t -> Pdf.t - -type attachment = - {name : string; - pagenumber : int; - data : unit -> Pdfio.bytes} - -(** List attached files. Attachment name and page number. Page 0 is document level. *) -val list_attached_files : Pdf.t -> attachment list - (** {2 Bookmarks} *) (** [parse_bookmark_file verify pdf input] parses the bookmark file in [input]. diff --git a/cpdfattach.ml b/cpdfattach.ml new file mode 100644 index 0000000..f9c790c --- /dev/null +++ b/cpdfattach.ml @@ -0,0 +1,226 @@ +open Pdfutil +open Pdfio +open Cpdferror + +(* Attaching files *) +let attach_file ?memory keepversion topage pdf file = + let data = + match memory with + Some data -> data + | None -> + let ch = open_in_bin file in + let len = in_channel_length ch in + let stream = mkbytes len in + let i = input_of_channel ch in + setinit i stream 0 len; + close_in ch; + stream + in + let filestream = + Pdf.Stream + (ref (Pdf.Dictionary + [("/Length", Pdf.Integer (bytes_size data)); + ("/Type", Pdf.Name "/EmbeddedFile"); + ("/Params", + Pdf.Dictionary + [("/Size", Pdf.Integer (bytes_size data)); + ("/CheckSum", Pdf.String (Digest.string (string_of_bytes data))) + ])], + Pdf.Got data)) + in + let filestream_num = Pdf.addobj pdf filestream in + let basename = Pdftext.pdfdocstring_of_utf8 (Filename.basename file) in + let filespec = + Pdf.Dictionary + [("/EF", Pdf.Dictionary ["/F", Pdf.Indirect filestream_num]); + ("/F", Pdf.String basename); + ("/Type", Pdf.Name "/Filespec"); + ("/Desc", Pdf.String ""); + ("/UF", Pdf.String basename)] + in + match topage with + | None -> + (* Look up /Names and /EmbeddedFiles and /Names. *) + let rootdict = Pdf.lookup_obj pdf pdf.Pdf.root in + let namedict = + match Pdf.lookup_direct pdf "/Names" rootdict with + | None -> Pdf.Dictionary [] + | Some namedict -> namedict + in + let embeddednamedict = + match Pdf.lookup_direct pdf "/EmbeddedFiles" namedict with + | None -> Pdf.Dictionary [] + | Some embeddednamedict -> embeddednamedict + in + let elts = + match Pdf.lookup_direct pdf "/Names" embeddednamedict with + | Some (Pdf.Array elts) -> elts + | _ -> [] + in + let filespecobj = Pdf.addobj pdf filespec in + let names' = Pdf.Array (elts @ [Pdf.String basename; Pdf.Indirect filespecobj]) in + let embeddednamedict' = Pdf.add_dict_entry embeddednamedict "/Names" names' in + let namedict' = Pdf.add_dict_entry namedict "/EmbeddedFiles" embeddednamedict' in + let rootdict' = Pdf.add_dict_entry rootdict "/Names" namedict' in + let rootnum = Pdf.addobj pdf rootdict' in + {pdf with + Pdf.minor = if keepversion then pdf.Pdf.minor else max pdf.Pdf.minor 4; + Pdf.root = rootnum; + Pdf.trailerdict = + Pdf.add_dict_entry + pdf.Pdf.trailerdict "/Root" (Pdf.Indirect rootnum)} + | Some pagenumber -> + let pages = Pdfpage.pages_of_pagetree pdf in + if pagenumber < 0 || pagenumber > length pages then error "attach_file: Page not found" else + let page = select pagenumber pages in + let annots = + match Pdf.lookup_direct pdf "/Annots" page.Pdfpage.rest with + | Some (Pdf.Array annots) -> annots + | _ -> [] + in + let rect = + let minx, miny, maxx, maxy = Pdf.parse_rectangle page.Pdfpage.mediabox in + Pdf.Array [Pdf.Real 18.; Pdf.Real (maxy -. 45.); Pdf.Real 45.; Pdf.Real (maxy -. 18.)] + in + let filespecobj = Pdf.addobj pdf filespec in + let annot = + Pdf.Dictionary + [("/FS", Pdf.Indirect filespecobj); + ("/Subtype", Pdf.Name "/FileAttachment"); + ("/Contents", Pdf.String basename); + ("/Rect", rect)] + in + let annots' = Pdf.Array (annot::annots) in + let page' = + {page with Pdfpage.rest = Pdf.add_dict_entry page.Pdfpage.rest "/Annots" annots'} + in + let pages' = replace_number pagenumber page' pages in + let pdf = Pdfpage.change_pages true pdf pages' in + {pdf with + Pdf.minor = if keepversion then pdf.Pdf.minor else max pdf.Pdf.minor 4} + +type attachment = + {name : string; + pagenumber : int; + data : unit -> Pdfio.bytes} + +let list_attached_files pdf = + let toplevel = + match Pdf.lookup_direct pdf "/Root" pdf.Pdf.trailerdict with + | None -> [] + | Some rootdict -> + match Pdf.lookup_direct pdf "/Names" rootdict with + | None -> [] + | Some namedict -> + match Pdf.lookup_direct pdf "/EmbeddedFiles" namedict with + | Some nametree -> + map + (function (x, ef) -> + match Pdf.lookup_direct pdf "/EF" ef with + | Some ((Pdf.Dictionary _) as d) -> + begin match Pdf.lookup_direct pdf "/F" d with + | Some stream -> + {name = x; + pagenumber = 0; + data = + (fun () -> + try + Pdf.getstream stream; + Pdfcodec.decode_pdfstream pdf stream; + match stream with + Pdf.Stream {contents = (_, Pdf.Got data)} -> data + | _ -> raise Not_found + with + _ -> raise (Pdf.PDFError "could not retreive attachment data"))} + | None -> raise (Pdf.PDFError "/F not found") + end + | _ -> raise (Pdf.PDFError "/EF not found")) + (option_map + (function (Pdf.String s, ef) -> Some (s, ef) | _ -> None) + (Pdf.contents_of_nametree pdf nametree)) + | _ -> [] + in let pagelevel = + let pages = Pdfpage.pages_of_pagetree pdf in + flatten + (map2 + (fun page pagenumber -> + option_map + (function annot -> + match Pdf.lookup_direct pdf "/Subtype" annot with + | Some (Pdf.Name "/FileAttachment") -> + (match Pdf.lookup_direct pdf "/Contents" annot with + | Some (Pdf.String s) -> + begin match Pdf.lookup_direct pdf "/FS" annot with + | Some ((Pdf.Dictionary _) as d) -> + (*Printf.eprintf "%s\n%!" (Pdfwrite.string_of_pdf d);*) + begin match Pdf.lookup_direct pdf "/EF" d with + | Some ((Pdf.Dictionary _) as d) -> + begin match Pdf.lookup_direct pdf "/F" d with + | Some stream -> + Some + {name = s; + pagenumber = pagenumber; + data = + (fun () -> + try + Pdf.getstream stream; + Pdfcodec.decode_pdfstream pdf stream; + match stream with + Pdf.Stream {contents = (_, Pdf.Got data)} -> data + | _ -> raise Not_found + with + _ -> raise (Pdf.PDFError "could not retreive attachment data"))} + | _ -> raise (Pdf.PDFError "no /F found in attachment") + end + | _ -> + Some + {name = s; + pagenumber = pagenumber; + data = (fun () -> raise (Pdf.PDFError "no attachment data"))} + end + | _ -> None + end + | _ -> None) + | _ -> None) + (match Pdf.lookup_direct pdf "/Annots" page.Pdfpage.rest with + | Some (Pdf.Array annots) -> annots + | _ -> [])) + pages + (indx pages)) + in + toplevel @ pagelevel + +(* \section{Remove Attached files} *) +let remove_attached_files_on_pages pdf = + let remove_from_page page = + {page with Pdfpage.rest = + Pdf.add_dict_entry page.Pdfpage.rest "/Annots" + (Pdf.Array + (option_map + (function annot -> + match Pdf.lookup_direct pdf "/Subtype" annot with + | Some (Pdf.Name "/FileAttachment") -> None + | _ -> Some annot) + (match Pdf.lookup_direct pdf "/Annots" page.Pdfpage.rest with + | Some (Pdf.Array annots) -> annots + | _ -> [])))} + in + Pdfpage.change_pages true pdf (map remove_from_page (Pdfpage.pages_of_pagetree pdf)) + +let remove_attached_files pdf = + let pdf = remove_attached_files_on_pages pdf in + match Pdf.lookup_direct pdf "/Root" pdf.Pdf.trailerdict with + | None -> pdf + | Some rootdict -> + match Pdf.lookup_direct pdf "/Names" rootdict with + | None -> pdf + | Some namedict -> + let namedict' = Pdf.remove_dict_entry namedict "/EmbeddedFiles" in + let rootdict' = Pdf.add_dict_entry rootdict "/Names" namedict' in + let rootdict'num = Pdf.addobj pdf rootdict' in + {pdf with + Pdf.root = + rootdict'num; + Pdf.trailerdict = + Pdf.add_dict_entry pdf.Pdf.trailerdict "/Root" (Pdf.Indirect rootdict'num)} + diff --git a/cpdfattach.mli b/cpdfattach.mli new file mode 100644 index 0000000..c9ae94e --- /dev/null +++ b/cpdfattach.mli @@ -0,0 +1,14 @@ +(** {2 File Attachments} *) +(** [attach_file keepversion topage pdf filename] attaches the file in [filename] to the pdf, optionally to a page (rather than document-level). If keepversion is true, the PDF version number won't be altered. *) +val attach_file : ?memory:Pdfio.bytes -> bool -> int option -> Pdf.t -> string -> Pdf.t + +(** Remove attached files. *) +val remove_attached_files : Pdf.t -> Pdf.t + +type attachment = + {name : string; + pagenumber : int; + data : unit -> Pdfio.bytes} + +(** List attached files. Attachment name and page number. Page 0 is document level. *) +val list_attached_files : Pdf.t -> attachment list diff --git a/cpdfcommand.ml b/cpdfcommand.ml index c9a54d9..a6bfbe4 100644 --- a/cpdfcommand.ml +++ b/cpdfcommand.ml @@ -27,17 +27,17 @@ it had been loaded. *) let pdfread_pdf_of_input ?revision a b c = try Pdfread.pdf_of_input ?revision a b c with Pdf.PDFError s when String.length s >=10 && String.sub s 0 10 = "Encryption" -> - raise (Cpdf.SoftError "Bad owner or user password when reading document") + raise (Cpdferror.SoftError "Bad owner or user password when reading document") let pdfread_pdf_of_channel_lazy ?revision ?source b c d = try Pdfread.pdf_of_channel_lazy ?revision ?source b c d with Pdf.PDFError s when String.length s >=10 && String.sub s 0 10 = "Encryption" -> - raise (Cpdf.SoftError "Bad owner or user password when reading document") + raise (Cpdferror.SoftError "Bad owner or user password when reading document") let pdfread_pdf_of_file ?revision a b c = try Pdfread.pdf_of_file ?revision a b c with Pdf.PDFError s when String.length s >=10 && String.sub s 0 10 = "Encryption" -> - raise (Cpdf.SoftError "Bad owner or user password when reading document") + raise (Cpdferror.SoftError "Bad owner or user password when reading document") let optstring = function | "" -> None @@ -2352,7 +2352,7 @@ let rec get_single_pdf ?(decrypt=true) ?(fail=false) op read_lazy = else pdfread_pdf_of_file ?revision (optstring u) (optstring o) inname with - | Cpdf.SoftError _ as e -> raise e (* Bad owner or user password *) + | Cpdferror.SoftError _ as e -> raise e (* Bad owner or user password *) | _ -> if args.gs_malformed then begin @@ -2446,7 +2446,7 @@ let rec get_pdf_from_input_kind ?(read_lazy=false) ?(decrypt=true) ?(fail=false) else pdfread_pdf_of_file ?revision (optstring u) (optstring o) s with - | Cpdf.SoftError _ as e -> raise e (* Bad owner or user password *) + | Cpdferror.SoftError _ as e -> raise e (* Bad owner or user password *) | e -> Printf.printf "%s\n" (Printexc.to_string e); if args.gs_malformed then @@ -4046,9 +4046,9 @@ let go () = write_pdf false (Cpdf.scale_contents ~fast:args.fast args.position scale pdf range) | Some ListAttachedFiles -> let pdf = get_single_pdf args.op false in - let attachments = Cpdf.list_attached_files pdf in + let attachments = Cpdfattach.list_attached_files pdf in iter - (fun a -> Printf.printf "%i %s\n" a.Cpdf.pagenumber a.Cpdf.name) + (fun a -> Printf.printf "%i %s\n" a.Cpdfattach.pagenumber a.Cpdfattach.name) attachments; flprint "" | Some DumpAttachedFiles -> @@ -4059,7 +4059,7 @@ let go () = | Stdout -> error "Can't dump attachments to stdout" end | Some RemoveAttachedFiles -> - write_pdf false (Cpdf.remove_attached_files (get_single_pdf args.op false)) + write_pdf false (Cpdfattach.remove_attached_files (get_single_pdf args.op false)) | Some (AttachFile files) -> begin match args.inputs with | [(k, _, _, _, _, _) as input] -> @@ -4072,7 +4072,7 @@ let go () = | Some s -> Some (int_of_string s) with _ -> error "Bad -to-page" in - let pdf = fold_left (Cpdf.attach_file args.keepversion topage) pdf (rev files) in + let pdf = fold_left (Cpdfattach.attach_file args.keepversion topage) pdf (rev files) in write_pdf false pdf | _ -> error "attach file: No input file specified" end @@ -4499,8 +4499,8 @@ let go_withargv argv = if args.debug then raise e else exit 2 else raise StayOnError - | Cpdf.SoftError s -> soft_error s - | Cpdf.HardError s -> error s + | Cpdferror.SoftError s -> soft_error s + | Cpdferror.HardError s -> error s | e -> prerr_string ("cpdf encountered an unexpected error. Technical Details follow:\n" ^ diff --git a/cpdferror.ml b/cpdferror.ml new file mode 100644 index 0000000..2329e61 --- /dev/null +++ b/cpdferror.ml @@ -0,0 +1,9 @@ +(** Two exceptions recommended for use with the library, though currently not +raised by any function in this module. Cpdfcommand uses them extensively. *) +exception SoftError of string + +exception HardError of string + +let error s = raise (SoftError s) + + diff --git a/cpdferror.mli b/cpdferror.mli new file mode 100644 index 0000000..3061dee --- /dev/null +++ b/cpdferror.mli @@ -0,0 +1,3 @@ +exception SoftError of string +val error : string -> 'a +exception HardError of string