Pdfcrowd - pdfcrowd.php

raw code

  1 <?php
  2 
  3 // Copyright (C) 2010-2014 pdfcrowd.com
  4 //
  5 // Inspired by code written by Jawaad Mahmood
  6 //  <http://www.tokyomuslim.com/2010/04/php-class-to-run-pdfcrowd-com/>
  7 // 
  8 // Permission is hereby granted, free of charge, to any person
  9 // obtaining a copy of this software and associated documentation
 10 // files (the "Software"), to deal in the Software without
 11 // restriction, including without limitation the rights to use,
 12 // copy, modify, merge, publish, distribute, sublicense, and/or sell
 13 // copies of the Software, and to permit persons to whom the
 14 // Software is furnished to do so, subject to the following
 15 // conditions:
 16 // 
 17 // The above copyright notice and this permission notice shall be
 18 // included in all copies or substantial portions of the Software.
 19 // 
 20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 22 // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 24 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 25 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 26 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 27 // OTHER DEALINGS IN THE SOFTWARE.
 28 
 29 
 30 
 31 //
 32 // Thrown when an error occurs.
 33 // 
 34 class PdfcrowdException extends Exception {
 35     // custom string representation of object
 36     public function __toString() {
 37         if ($this->code) {
 38             return "[{$this->code}] {$this->message}\n";
 39         } else {
 40             return "{$this->message}\n";
 41         }
 42     }
 43 }
 44 
 45 
 46 //
 47 // Pdfcrowd API client.
 48 // 
 49 class PdfCrowd {
 50     //
 51     // Pdfcrowd constructor.
 52     // 
 53     // $username - your username at Pdfcrowd
 54     // $apikey  - your API key
 55     // $hostname - API hostname, defaults to pdfcrowd.com
 56     // 
 57     function __construct($username, $apikey, $hostname=null){
 58         if ($hostname)
 59             $this->hostname = $hostname;
 60         else
 61             $this->hostname = self::$api_host;
 62         $this->useSSL(false);
 63         $this->fields = array(
 64             'username' => $username,
 65             'key' => $apikey,
 66             'pdf_scaling_factor' => 1,
 67             'html_zoom' => 200);
 68         $this->proxy_name = null;
 69         $this->proxy_port = null;
 70         $this->proxy_username = "";
 71         $this->proxy_password = "";
 72         
 73         $this->user_agent = "pdfcrowd_php_client_".self::$client_version."_(http://pdfcrowd.com)";
 74     }
 75 
 76     //
 77     // Converts an in-memory html document.
 78     //
 79     // $src       - a string containing a html document
 80     // $outstream - output stream, if null then the return value is a string
 81     //              containing the PDF
 82     // 
 83     function convertHtml($src, $outstream=null){
 84         if (!$src) {
 85             throw new PdfcrowdException("convertHTML(): the src parameter must not be empty");
 86         }
 87         
 88         $this->fields['src'] = $src;
 89         $uri = $this->api_prefix . "/pdf/convert/html/";
 90         $postfields = http_build_query($this->fields, '', '&');
 91         return $this->http_post($uri, $postfields, $outstream);
 92     }
 93 
 94     //
 95     // Converts an html file.
 96     //
 97     // $src       - a path to an html file
 98     // $outstream - output stream, if null then the return value is a string
 99     //              containing the PDF
100     // 
101     function convertFile($src, $outstream=null) {
102         $src = trim($src);
103 
104         if (!file_exists($src)) {
105             $cwd = getcwd();
106             throw new PdfcrowdException("convertFile(): '{$src}' not found
107 Possible reasons:
108  1. The file is missing.
109  2. You misspelled the file name.
110  3. You use a relative file path (e.g. 'index.html') but the current working
111     directory is somewhere else than you expect: '${cwd}'
112     Generally, it is safer to use an absolute file path instead of a relative one.
113 ");
114         }
115 
116         if (is_dir($src)) {
117             throw new PdfcrowdException("convertFile(): '{$src}' must be file, not a directory");
118         }
119 
120         if (!is_readable($src)) {
121             throw new PdfcrowdException("convertFile(): cannot read '{$src}', please check if the process has sufficient permissions");
122         }
123 
124         if (!filesize($src)) {
125             throw new PdfcrowdException("convertFile(): '{$src}' must not be empty");
126         }
127 
128         if (version_compare(PHP_VERSION, '5.5.0') >= 0) {
129             $this->fields['src'] = new CurlFile($src);
130         } else {
131             $this->fields['src'] = '@' . $src;
132         }
133 
134         $uri = $this->api_prefix . "/pdf/convert/html/";
135         return $this->http_post($uri, $this->fields, $outstream);
136     }
137     
138     //
139     // Converts a web page.
140     //
141     // $src       - a web page URL
142     // $outstream - output stream, if null then the return value is a string
143     //              containing the PDF
144     // 
145     function convertURI($src, $outstream=null){
146         $src = trim($src);
147         if (!preg_match("/^https?:\/\/.*/i", $src)) {
148             throw new PdfcrowdException("convertURI(): the URL must start with http:// or https:// (got '$src')");
149         }
150         
151         $this->fields['src'] = $src;
152         $uri = $this->api_prefix . "/pdf/convert/uri/";
153         $postfields = http_build_query($this->fields, '', '&');
154         return $this->http_post($uri, $postfields, $outstream);
155     }
156 
157     //
158     // Returns the number of available conversion tokens.
159     // 
160     function numTokens() {
161         $username = $this->fields['username'];
162         $uri = $this->api_prefix . "/user/{$username}/tokens/";
163         $arr = array('username' => $this->fields['username'],
164                      'key' => $this->fields['key']);
165         $postfields = http_build_query($arr, '', '&');
166         $ntokens = $this->http_post($uri, $postfields, NULL);
167         return (int)$ntokens;
168     }
169 
170     function useSSL($use_ssl) {
171         if($use_ssl) {
172             $this->port = self::$https_port;
173             $this->scheme = 'https';
174         }
175         else {
176             $this->port = self::$http_port;
177             $this->scheme = 'http';
178         }
179 
180         $this->api_prefix = "{$this->scheme}://{$this->hostname}/api";
181     }
182 
183     function setPageWidth($value) {
184         $this->fields['width'] = $value;
185     }
186     
187     function setPageHeight($value) {
188         $this->fields['height'] = $value;
189     }
190     
191     function setHorizontalMargin($value) {
192         $this->fields['margin_right'] = $this->fields['margin_left'] = $value;
193     }
194     
195     function setVerticalMargin($value) {
196         $this->fields['margin_top'] = $this->fields['margin_bottom'] = $value;
197     }
198 
199     function setPageMargins($top, $right, $bottom, $left) {
200       $this->fields['margin_top'] = $top;
201       $this->fields['margin_right'] = $right;
202       $this->fields['margin_bottom'] = $bottom;
203       $this->fields['margin_left'] = $left;
204     }
205 
206     function setEncrypted($val=True) {
207         $this->set_or_unset($val, 'encrypted');
208     }
209     
210     function setUserPassword($pwd) {
211         $this->set_or_unset($pwd, 'user_pwd');
212     }
213     
214     function setOwnerPassword($pwd) {
215         $this->set_or_unset($pwd, 'owner_pwd');
216     }
217     
218     function setNoPrint($val=True) {
219         $this->set_or_unset($val, 'no_print');
220     }
221     
222     function setNoModify($val=True) {
223         $this->set_or_unset($val, 'no_modify');
224     }
225     
226     function setNoCopy($val=True) {
227         $this->set_or_unset($val, 'no_copy');
228     }
229 
230     // constants for setPageLayout()
231     const SINGLE_PAGE = 1;
232     const CONTINUOUS = 2;
233     const CONTINUOUS_FACING = 3;
234     
235     function setPageLayout($value) {
236         assert($value > 0 && $value <= 3);
237         $this->fields['page_layout'] = $value;
238     }
239 
240     // constants for setPageMode()
241     const NONE_VISIBLE = 1;
242     const THUMBNAILS_VISIBLE = 2;
243     const FULLSCREEN = 3;
244     
245     function setPageMode($value) {
246         assert($value > 0 && $value <= 3);
247         $this->fields['page_mode'] = $value;
248     }
249     
250     function setFooterText($value) {
251         $this->set_or_unset($value, 'footer_text');
252     }
253     
254     function enableImages($value=True) {
255         $this->set_or_unset(!$value, 'no_images');
256     }
257     
258     function enableBackgrounds($value=True) {
259         $this->set_or_unset(!$value, 'no_backgrounds');
260     }
261     
262     function setHtmlZoom($value) {
263         $this->set_or_unset($value, 'html_zoom');
264     }
265     
266     function enableJavaScript($value=True) {
267         $this->set_or_unset(!$value, 'no_javascript');
268     }
269     
270     function enableHyperlinks($value=True) {
271         $this->set_or_unset(!$value, 'no_hyperlinks');
272     }
273     
274     function setDefaultTextEncoding($value) {
275         $this->set_or_unset($value, 'text_encoding');
276     }
277     
278     function usePrintMedia($value=True) {
279         $this->set_or_unset($value, 'use_print_media');
280     }
281     
282     function setMaxPages($value) {
283         $this->fields['max_pages'] = $value;
284     }
285     
286     function enablePdfcrowdLogo($value=True) {
287         $this->set_or_unset($value, 'pdfcrowd_logo');
288     }
289 
290     // constants for setInitialPdfZoomType()
291     const FIT_WIDTH = 1;
292     const FIT_HEIGHT = 2;
293     const FIT_PAGE = 3;
294     
295     function setInitialPdfZoomType($value) {
296         assert($value>0 && $value<=3);
297         $this->fields['initial_pdf_zoom_type'] = $value;
298     }
299     
300     function setInitialPdfExactZoom($value) {
301         $this->fields['initial_pdf_zoom_type'] = 4;
302         $this->fields['initial_pdf_zoom'] = $value;
303     }
304 
305     function setPdfScalingFactor($value) {
306         $this->fields['pdf_scaling_factor'] = $value;
307     }
308 
309     function setAuthor($value) {
310         $this->fields['author'] = $value;
311     }
312 
313     function setFailOnNon200($value) {
314         $this->fields['fail_on_non200'] = $value;
315     }
316 
317     function setFooterHtml($value) {
318         $this->fields['footer_html'] = $value;
319     }
320         
321     function setFooterUrl($value) {
322         $this->fields['footer_url'] = $value;
323     }
324         
325     function setHeaderHtml($value) {
326         $this->fields['header_html'] = $value;
327     }
328         
329     function setHeaderUrl($value) {
330         $this->fields['header_url'] = $value;
331     }
332 
333     function setPageBackgroundColor($value) {
334         $this->fields['page_background_color'] = $value;
335     }
336     
337     function setTransparentBackground($value=True) {
338         $this->set_or_unset($value, 'transparent_background');
339     }
340 
341     function setPageNumberingOffset($value) {
342         $this->fields['page_numbering_offset'] = $value;
343     }
344 
345     function setHeaderFooterPageExcludeList($value) {
346         $this->fields['header_footer_page_exclude_list'] = $value;
347     }
348         
349     function setWatermark($url, $offset_x=0, $offset_y=0) {
350         $this->fields["watermark_url"] = $url;
351         $this->fields["watermark_offset_x"] = $offset_x;
352         $this->fields["watermark_offset_y"] = $offset_y;
353     }
354     
355     function setWatermarkRotation($angle) {
356         $this->fields["watermark_rotation"] = $angle;
357     }
358 
359     function setWatermarkInBackground($val=True) {
360         $this->set_or_unset($val, "watermark_in_background");
361     }
362 
363     function setProxy($proxyname, $port, $username="", $password="") {
364         $this->proxy_name = $proxyname;
365         $this->proxy_port = $port;
366         $this->proxy_username = $username;
367         $this->proxy_password = $password;
368     }
369 
370     function setUserAgent($user_agent) {
371         $this->user_agent = $user_agent;
372     }
373     
374     
375 
376 
377     // ----------------------------------------------------------------------
378     //
379     //                        Private stuff
380     //
381 
382     private $fields, $scheme, $port, $api_prefix;
383 
384     public static $client_version = "2.7";
385     public static $http_port = 80;
386     public static $https_port = 443;
387     public static $api_host = 'pdfcrowd.com';
388 
389     private static $missing_curl = 'pdfcrowd.php requires cURL which is not installed on your system.
390 
391 How to install:
392   Windows: uncomment/add the "extension=php_curl.dll" line in php.ini
393   Linux:   should be a part of the distribution, 
394            e.g. on Debian/Ubuntu run "sudo apt-get install php5-curl"
395 
396 You need to restart your web server after installation.
397 
398 Links:
399  Installing the PHP/cURL binding:  <http://curl.haxx.se/libcurl/php/install.html>
400  PHP/cURL documentation:           <http://cz.php.net/manual/en/book.curl.php>';
401 
402 
403     private function http_post($url, $postfields, $outstream) {
404         if (!function_exists("curl_init")) {
405             throw new PdfcrowdException(self::$missing_curl);
406         }
407         
408         $c = curl_init();
409         curl_setopt($c, CURLOPT_URL,$url);
410         curl_setopt($c, CURLOPT_HEADER, false);
411         curl_setopt($c, CURLOPT_CONNECTTIMEOUT, 10);
412         curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
413         curl_setopt($c, CURLOPT_POST, true);
414         curl_setopt($c, CURLOPT_PORT, $this->port);
415         curl_setopt($c, CURLOPT_POSTFIELDS, $postfields);
416         curl_setopt($c, CURLOPT_DNS_USE_GLOBAL_CACHE, false);
417         curl_setopt($c, CURLOPT_USERAGENT, $this->user_agent);
418         if ($outstream) {
419             $this->outstream = $outstream;
420             curl_setopt($c, CURLOPT_WRITEFUNCTION, array($this, 'receive_to_stream'));
421         }
422 
423         if ($this->scheme == 'https' && self::$api_host == 'pdfcrowd.com') {
424             curl_setopt($c, CURLOPT_SSL_VERIFYPEER, true);
425         } else {
426             curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
427         }
428 
429         if ($this->proxy_name) {
430             curl_setopt($c, CURLOPT_PROXY, $this->proxy_name . ":" . $this->proxy_port);
431             if ($this->proxy_username) {
432                 curl_setopt($c, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
433                 curl_setopt($c, CURLOPT_PROXYUSERPWD, $this->proxy_username . ":" . $this->proxy_password);
434             }
435         }
436 
437         $this->http_code = 0;
438         $this->error = "";
439 
440         $response = curl_exec($c);
441         $this->http_code = curl_getinfo($c, CURLINFO_HTTP_CODE);
442         $error_str = curl_error($c);
443         $error_nr = curl_errno($c);
444         curl_close($c);
445 
446         if ($error_nr != 0) {
447             throw new PdfcrowdException($error_str, $error_nr);            
448         }
449         else if ($this->http_code == 200) {
450             if ($outstream == NULL) {
451                 return $response;
452             }
453         } else {
454             throw new PdfcrowdException($this->error ? $this->error : $response, $this->http_code);
455         }
456     }
457 
458     private function receive_to_stream($curl, $data) {
459         if ($this->http_code == 0) {
460             $this->http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
461         }
462 
463         if ($this->http_code >= 400) {
464             $this->error = $this->error . $data;
465             return strlen($data);
466         }
467         
468         $written = fwrite($this->outstream, $data);
469         if ($written != strlen($data)) {
470             if (get_magic_quotes_runtime()) {
471                 throw new PdfcrowdException("Cannot write the PDF file because the 'magic_quotes_runtime' setting is enabled.
472 Please disable it either in your php.ini file, or in your code by calling 'set_magic_quotes_runtime(false)'.");
473             } else {
474                 throw new PdfcrowdException('Writing the PDF file failed. The disk may be full.');
475             }
476         }
477         return $written;
478     }
479 
480     private function set_or_unset($val, $field) {
481         if ($val)
482             $this->fields[$field] = $val;
483         else
484             unset($this->fields[$field]);
485     }
486 
487     
488 }
489 
490 ?>