pdfcrowd 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
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
+