pdfcrowd 1.8.0

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 (2) hide show
  1. data/lib/pdfcrowd.rb +468 -0
  2. metadata +65 -0
@@ -0,0 +1,468 @@
1
+ # Copyright (C) 2009-2011 pdfcrowd.com
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person
4
+ # obtaining a copy of this software and associated documentation
5
+ # files (the "Software"), to deal in the Software without
6
+ # restriction, including without limitation the rights to use,
7
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the
9
+ # Software is furnished to do so, subject to the following
10
+ # conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ # OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ require 'net/http'
25
+ require 'cgi'
26
+
27
+
28
+ module Pdfcrowd
29
+ # constants for setPageLayout()
30
+ SINGLE_PAGE, CONTINUOUS, CONTINUOUS_FACING = 1, 2, 3
31
+
32
+ # constants for setPageMode()
33
+ NONE_VISIBLE, THUMBNAILS_VISIBLE, FULLSCREEN = 1, 2, 3
34
+
35
+ # constants for setInitialPdfZoomType()
36
+ FIT_WIDTH, FIT_HEIGHT, FIT_PAGE = 1, 2, 3
37
+
38
+
39
+ #
40
+ # Thrown when an error occurs.
41
+ #
42
+ class Error < RuntimeError
43
+ attr_reader :http_code, :error
44
+
45
+ def initialize(error, http_code=nil)
46
+ super()
47
+ @http_code = http_code
48
+ @error = error
49
+ end
50
+
51
+ def to_s()
52
+ @http_code ? "#{@http_code} - #{@error}" : @error
53
+ end
54
+ end
55
+
56
+
57
+ #
58
+ # Pdfcrowd API client.
59
+ #
60
+ class Client
61
+
62
+ #
63
+ # Client constructor.
64
+ #
65
+ # username -- your username at Pdfcrowd
66
+ # apikey -- your API key
67
+ #
68
+ def initialize(username, apikey)
69
+ useSSL(false)
70
+ @fields = {
71
+ 'username' => username,
72
+ 'key' => apikey
73
+ }
74
+ end
75
+
76
+ #
77
+ # Converts a web page.
78
+ #
79
+ # uri -- a web page URL
80
+ # outstream -- an object having method 'write(data)'; if nil then the
81
+ # return value is a string containing the PDF.
82
+ #
83
+ def convertURI(uri, outstream=nil)
84
+ return convert(outstream, 'uri', uri)
85
+ end
86
+
87
+ #
88
+ # Converts an in-memory html document.
89
+ #
90
+ # content -- a string containing an html document
91
+ # outstream -- an object having method 'write(data)'; if nil then the
92
+ # return value is a string containing the PDF.
93
+ #
94
+ def convertHtml(content, outstream=nil)
95
+ return convert(outstream, 'html', content)
96
+ end
97
+
98
+ #
99
+ # Converts an html file.
100
+ #
101
+ # fpath -- a path to an html file
102
+ # outstream -- an object having method 'write(data)'; if nil then the
103
+ # return value is a string containing the PDF.
104
+ #
105
+ def convertFile(fpath, outstream=nil)
106
+ return post_multipart(fpath, outstream)
107
+ end
108
+
109
+ #
110
+ # Returns the number of available conversion tokens.
111
+ #
112
+ def numTokens()
113
+ uri = @api_uri + 'user/%s/tokens/' % @fields['username']
114
+ response = call_api(uri, nil)
115
+ return Integer(response)
116
+ end
117
+
118
+ def useSSL(use_ssl)
119
+ @use_ssl = use_ssl
120
+ @api_uri = use_ssl ? HTTPS_API_URI : HTTP_API_URI
121
+ end
122
+
123
+ def setUsername(username)
124
+ @fields['username'] = username
125
+ end
126
+
127
+ def setApiKey(key)
128
+ @fields['key'] = key
129
+ end
130
+
131
+ def setPageWidth(value)
132
+ @fields['width'] = value
133
+ end
134
+
135
+ def setPageHeight(value)
136
+ @fields['height'] = value
137
+ end
138
+
139
+ def setHorizontalMargin(value)
140
+ @fields['hmargin'] = value
141
+ end
142
+
143
+ def setVerticalMargin(value)
144
+ @fields['vmargin'] = value
145
+ end
146
+
147
+ def setEncrypted(val=true)
148
+ @fields['encrypted'] = val
149
+ end
150
+
151
+ def setUserPassword(pwd)
152
+ @fields['user_pwd'] = pwd
153
+ end
154
+
155
+ def setOwnerPassword(pwd)
156
+ @fields['owner_pwd'] = pwd
157
+ end
158
+
159
+ def setNoPrint(val=true)
160
+ @fields['no_print'] = val
161
+ end
162
+
163
+ def setNoModify(val=true)
164
+ @fields['no_modify'] = val
165
+ end
166
+
167
+ def setNoCopy(val=true)
168
+ @fields['no_copy'] = val
169
+ end
170
+
171
+ def setPageLayout(value)
172
+ assert { value > 0 and value <= 3 }
173
+ @fields['page_layout'] = value
174
+ end
175
+
176
+ def setPageMode(value)
177
+ assert { value > 0 and value <= 3 }
178
+ @fields['page_mode'] = value
179
+ end
180
+
181
+
182
+ def setFooterText(value)
183
+ @fields['footer_text'] = value
184
+ end
185
+
186
+ def enableImages(value=true)
187
+ @fields['no_images'] = (not value)
188
+ end
189
+
190
+ def enableBackgrounds(value=true)
191
+ @fields['no_backgrounds'] = (not value)
192
+ end
193
+
194
+ def setHtmlZoom(value)
195
+ @fields['html_zoom'] = value
196
+ end
197
+
198
+ def enableJavaScript(value=true)
199
+ @fields['no_javascript'] = (not value)
200
+ end
201
+
202
+ def enableHyperlinks(value=true)
203
+ @fields['no_hyperlinks'] = (not value)
204
+ end
205
+
206
+ def setDefaultTextEncoding(value)
207
+ @fields['text_encoding'] = value
208
+ end
209
+
210
+ def usePrintMedia(value=true)
211
+ @fields['use_print_media'] = value
212
+ end
213
+
214
+ def setMaxPages(value)
215
+ @fields['max_pages'] = value
216
+ end
217
+
218
+ def enablePdfcrowdLogo(value=true)
219
+ @fields['pdfcrowd_logo'] = value
220
+ end
221
+
222
+ def setInitialPdfZoomType(value)
223
+ assert { value>0 and value<=3 }
224
+ @fields['initial_pdf_zoom_type'] = value
225
+ end
226
+
227
+ def setInitialPdfExactZoom(value)
228
+ @fields['initial_pdf_zoom_type'] = 4
229
+ @fields['initial_pdf_zoom'] = value
230
+ end
231
+
232
+ def setPdfScalingFactor(value)
233
+ @fields['pdf_scaling_factor'] = value
234
+ end
235
+
236
+ def setFooterHtml(value)
237
+ @fields['footer_html'] = value
238
+ end
239
+
240
+ def setFooterUrl(value)
241
+ @fields['footer_url'] = value
242
+ end
243
+
244
+ def setHeaderHtml(value)
245
+ @fields['header_html'] = value
246
+ end
247
+
248
+ def setHeaderUrl(value)
249
+ @fields['header_url'] = value
250
+ end
251
+
252
+
253
+
254
+
255
+ # ----------------------------------------------------------------------
256
+ #
257
+ # Private stuff
258
+ #
259
+
260
+ private
261
+
262
+ def create_http_obj()
263
+ if @use_ssl
264
+ require 'net/https' #apt-get install libopenssl-ruby
265
+ http = Net::HTTP.new($api_hostname, $api_https_port)
266
+ # OpenSSL::SSL::VERIFY_PEER fails here:
267
+ # ... certificate verify failed ...
268
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
269
+ http.use_ssl = @use_ssl
270
+ else
271
+ http = Net::HTTP.new($api_hostname, $api_http_port)
272
+ end
273
+ return http
274
+ end
275
+
276
+ def convert(out_stream, method, src)
277
+ uri = @api_uri + 'pdf/convert/%s/' % method
278
+ return call_api(uri, out_stream, src)
279
+ end
280
+
281
+ def call_api(uri, out_stream, src=nil)
282
+ data = encode_post_data({'src' => src})
283
+ url = URI.parse(uri)
284
+ req = Net::HTTP::Post.new(url.path)
285
+ req.set_form_data(data)
286
+ http = create_http_obj()
287
+ begin
288
+ res = http.start {|connection| connection.request(req) }
289
+ case res
290
+ when Net::HTTPSuccess, Net::HTTPRedirection
291
+ if out_stream
292
+ out_stream.write(res.body)
293
+ return out_stream
294
+ else
295
+ return res.body
296
+ end
297
+ else
298
+ raise Error.new(res.body, res.code)
299
+ end
300
+ rescue SystemCallError => why
301
+ raise Error.new("#{why}\n")
302
+ end
303
+ end
304
+
305
+ def encode_post_data(extra_data={})
306
+ result = extra_data.clone()
307
+ @fields.each { |key, val| result[key] = val if val }
308
+ result
309
+ end
310
+
311
+ def encode_multipart_post_data(filename)
312
+ boundary = '----------ThIs_Is_tHe_bOUnDary_$'
313
+ body = []
314
+ for field, value in @fields
315
+ body << '--' + boundary << 'Content-Disposition: form-data; name="%s"' % field << '' << value.to_s if value
316
+ end
317
+ # filename
318
+ body << '--' + boundary
319
+ body << 'Content-Disposition: form-data; name="src"; filename="%s"' % filename
320
+ mime_type = 'application/octet-stream'
321
+ body << 'Content-Type: ' + mime_type
322
+ body << ''
323
+ body << open(filename).read()
324
+ # finalize
325
+ body << '--' + boundary + '--'
326
+ body << ''
327
+ body = body.join("\r\n")
328
+ content_type = 'multipart/form-data; boundary=%s' % boundary
329
+ return content_type, body
330
+ end
331
+
332
+ def post_multipart(fpath, out_stream)
333
+ content_type, body = encode_multipart_post_data(fpath)
334
+ headers = { 'content-type' => content_type, 'content-length' => body.length.to_s }
335
+ http = create_http_obj()
336
+ begin
337
+ res = http.start {|connection| connection.post(API_SELECTOR_BASE + 'pdf/convert/html/', body, headers) }
338
+ case res
339
+ when Net::HTTPSuccess, Net::HTTPRedirection
340
+ if out_stream
341
+ out_stream.write(res.body)
342
+ return out_stream
343
+ else
344
+ return res.body
345
+ end
346
+ else
347
+ raise Error.new(res.body, res.code)
348
+ end
349
+ rescue SystemCallError => why
350
+ raise Error.new("#{why}\n")
351
+ end
352
+ return
353
+ end
354
+ end
355
+ end
356
+
357
+
358
+ def assert
359
+ raise "Assertion failed !" unless yield
360
+ end
361
+
362
+
363
+ $api_hostname = 'pdfcrowd.com'
364
+ $api_http_port = 80
365
+ $api_https_port = 443
366
+
367
+
368
+ API_SELECTOR_BASE = '/api/'
369
+ HTTP_API_URI = "http://#{$api_hostname}#{API_SELECTOR_BASE}"
370
+ HTTPS_API_URI = "https://#{$api_hostname}#{API_SELECTOR_BASE}"
371
+
372
+
373
+
374
+ # ---------------------------------------------------------------------------
375
+ #
376
+ # Test
377
+ #
378
+
379
+ if __FILE__ == $0
380
+ if ARGV.length < 2
381
+ print "usage: ruby pdfcrowd.rb username apikey [hostname [http-port https-port]]\n"
382
+ exit 1
383
+ end
384
+
385
+ if ARGV.length > 2
386
+ $api_hostname=ARGV[2]
387
+ end
388
+
389
+ if ARGV.length == 5
390
+ $api_http_port=ARGV[3]
391
+ $api_https_port=ARGV[4]
392
+ end
393
+
394
+ print "using %s ports %d %d\n" % [$api_hostname, $api_http_port, $api_https_port]
395
+
396
+ some_html="<html><body>Uploaded content!</body></html>"
397
+ Dir.chdir(File.dirname($0))
398
+ $test_dir = '../../test_files'
399
+
400
+ def out_stream(name, use_ssl)
401
+ fname = "#{$test_dir}/out/rb_client_#{name}"
402
+ if use_ssl
403
+ fname = fname + '_ssl'
404
+ end
405
+ return open(fname + '.pdf', 'wb')
406
+ end
407
+
408
+ client = Pdfcrowd::Client.new(ARGV[0], ARGV[1])
409
+ for use_ssl in [false, true]
410
+ client.useSSL(use_ssl)
411
+ begin
412
+ ntokens = client.numTokens()
413
+ client.convertURI('http://www.jagpdf.org/', out_stream('uri', use_ssl))
414
+ client.convertHtml(some_html, out_stream('content', use_ssl))
415
+ client.convertFile("#{$test_dir}/in/simple.html", out_stream('upload', use_ssl))
416
+ client.convertFile("#{$test_dir}/in/archive.tar.gz", out_stream('archive', use_ssl))
417
+ after_tokens = client.numTokens()
418
+ if ntokens-4 != after_tokens
419
+ raise RuntimeError, 'got unexpected number of tokens'
420
+ end
421
+ print "remaining tokens: %d \n" % client.numTokens()
422
+ rescue Pdfcrowd::Error => why
423
+ print 'FAILED: ', why
424
+ exit(1)
425
+ end
426
+ end
427
+ # test individual methods
428
+ begin
429
+ for method, arg in [[:setPageWidth, 500],
430
+ [:setPageHeight, -1],
431
+ [:setHorizontalMargin, 72],
432
+ [:setVerticalMargin, 72],
433
+ [:setEncrypted, true],
434
+ [:setUserPassword, 'userpwd'],
435
+ [:setOwnerPassword, 'ownerpwd'],
436
+ [:setNoPrint, true],
437
+ [:setNoModify, true],
438
+ [:setNoCopy, true],
439
+ [:setPageLayout, Pdfcrowd::CONTINUOUS],
440
+ [:setPageMode, Pdfcrowd::FULLSCREEN],
441
+ [:setFooterText, '%p/%n | source %u'],
442
+ [:enableImages, false],
443
+ [:enableBackgrounds, false],
444
+ [:setHtmlZoom, 300],
445
+ [:enableJavaScript, false],
446
+ [:enableHyperlinks, false],
447
+ [:setDefaultTextEncoding, 'iso-8859-1'],
448
+ [:usePrintMedia, true],
449
+ [:setMaxPages, 1],
450
+ [:enablePdfcrowdLogo, true],
451
+ [:setInitialPdfZoomType, Pdfcrowd::FIT_PAGE],
452
+ [:setInitialPdfExactZoom, 113],
453
+ [:setFooterHtml, '<b>bold</b> and <i>italic</i> <img src="http://pdfcrowd.com/static/images/logo175x30.png" />'],
454
+ [:setFooterUrl, 'http://google.com'],
455
+ [:setHeaderHtml, 'page %p out of %n'],
456
+ [:setHeaderUrl, 'http://google.com'],
457
+ [:setPdfScalingFactor, 0.5]]
458
+ client = Pdfcrowd::Client.new(ARGV[0], ARGV[1])
459
+ client.setVerticalMargin("1in")
460
+ client.send(method, arg)
461
+ client.convertFile("#{$test_dir}/in/simple.html", out_stream(method.id2name.downcase(), false))
462
+ end
463
+ rescue Pdfcrowd::Error => why
464
+ print 'FAILED: ', why
465
+ exit(1)
466
+ end
467
+
468
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pdfcrowd
3
+ version: !ruby/object:Gem::Version
4
+ hash: 55
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 8
9
+ - 0
10
+ version: 1.8.0
11
+ platform: ruby
12
+ authors:
13
+ - Pdfcrowd Team
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-05-17 00:00:00 Z
19
+ dependencies: []
20
+
21
+ description: It lets you easily convert web pages and raw HTML code to PDF in your Ruby applications.
22
+ email: info@pdfcrowd.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - lib/pdfcrowd.rb
31
+ homepage: https://pdfcrowd.com/html-to-pdf-api/
32
+ licenses: []
33
+
34
+ post_install_message:
35
+ rdoc_options: []
36
+
37
+ require_paths:
38
+ - lib
39
+ required_ruby_version: !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ hash: 3
54
+ segments:
55
+ - 0
56
+ version: "0"
57
+ requirements: []
58
+
59
+ rubyforge_project:
60
+ rubygems_version: 1.7.2
61
+ signing_key:
62
+ specification_version: 3
63
+ summary: A client for the Pdfcrowd HTML to PDF API.
64
+ test_files: []
65
+