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 ?>