Pdfcrowd - Client.cs

raw code

  1 // Copyright (C) 2009-2013 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 using System;
 25 using System.Text;
 26 using System.Net;
 27 using System.IO;
 28 using System.Web;
 29 using System.Diagnostics;
 30 using System.Collections;
 31 using System.Collections.Generic;
 32 using System.Collections.Specialized;
 33 using System.Net.Security;
 34 
 35 namespace pdfcrowd
 36 {
 37   //
 38   // Pdfcrowd API client.
 39   // 
 40   public class Client
 41   {
 42     //
 43     // Client constructor.
 44     // 
 45     // username - your username at Pdfcrowd
 46     // api_key  - your API key
 47     // 
 48     public Client(string username, string api_key)
 49     {
 50       useSSL(false);
 51       fields.Add("username", username);
 52       fields.Add("key", api_key);
 53       fields.Add("pdf_scaling_factor", "1");
 54       fields.Add("html_zoom", "200");
 55     }
 56 
 57     //
 58     // Client constructor.
 59     // 
 60     // username - your username at Pdfcrowd
 61     // api_key  - your API key
 62     // 
 63     // 
 64     public Client(string username, string api_key, string hostname)
 65     {
 66       fields.Add("username", username);
 67       fields.Add("key", api_key);
 68       fields.Add("pdf_scaling_factor", "1");
 69       fields.Add("html_zoom", "200");
 70       HOST = hostname;
 71       useSSL(false);
 72     }
 73           
 74 
 75     //
 76     // Converts a web page.
 77     //
 78     // uri        - a web page URL
 79     // out_stream - a System.IO.Stream implementation
 80     // 
 81     public void convertURI(string uri, Stream out_stream)
 82     {
 83       convert(out_stream, "uri", uri);
 84     }
 85     
 86     //
 87     // Converts an in-memory html document.
 88     //
 89     // content    - a string containing a html document
 90     // out_stream - a System.IO.Stream implementation
 91     // 
 92     public void convertHtml(string content, Stream out_stream)
 93     {
 94       convert(out_stream, "html", content);
 95     }
 96 
 97     //
 98     // Converts an html file.
 99     //
100     // fpath      - a path to an html file
101     // out_stream - a System.IO.Stream implementation
102     // 
103     public void convertFile(string fpath, Stream out_stream)
104     {
105       post_multipart(fpath, out_stream);
106     }
107 
108     //
109     // Returns the number of available conversion tokens.
110     // 
111     public int numTokens()
112     {
113       string uri = String.Format("{0}user/{1}/tokens/", api_uri, fields["username"]);
114       MemoryStream stream = new MemoryStream();
115       call_api(uri, stream, null);
116       stream.Position = 0;
117       string value = read_stream(stream);
118       return Int32.Parse(value);
119     }
120           
121     
122     public void useSSL(bool use_ssl)
123     {
124       if(use_ssl)
125       {
126           api_uri = string.Format("https://{0}:{1}{2}", HOST, HTTPS_PORT, API_SELECTOR_BASE);
127       }
128       else
129       {
130           api_uri = string.Format("http://{0}:{1}{2}", HOST, HTTP_PORT, API_SELECTOR_BASE);
131       }
132     }
133     
134     public void setUsername(string username)
135     {
136       fields["username"] = username;
137     }
138 
139     public void setApiKey(string key)
140     {
141       fields["key"] = key;
142     }
143 
144     public void setPageWidth(string value)
145     {
146       fields["width"] = value;
147     }
148 
149     public void setPageWidth(double value)
150     {
151       fields["width"] = value.ToString();;
152     }
153         
154     public void setPageHeight(string value)
155     {
156       fields["height"] = value;
157     }
158           
159     public void setPageHeight(double value)
160     {
161       fields["height"] = value.ToString();
162     }
163 
164     public void setHorizontalMargin(double value) 
165     {
166       fields["margin_right"] = value.ToString();
167       fields["margin_left"] = value.ToString();
168     }
169 
170     public void setHorizontalMargin(string value) 
171     {
172       fields["margin_right"] = value;
173       fields["margin_left"] = value;
174     }
175 
176     public void setVerticalMargin(double value) 
177     {
178       fields["margin_top"] = value.ToString();
179       fields["margin_bottom"] = value.ToString();
180     }
181     
182     public void setVerticalMargin(string value) 
183     {
184       fields["margin_top"] = value;
185       fields["margin_bottom"] = value;
186     }
187 
188     public void setPageMargins(string top, string right, string bottom, string left) 
189     {
190       fields["margin_top"] = top;
191       fields["margin_right"] = right;
192       fields["margin_bottom"] = bottom;
193       fields["margin_left"] = left;
194     }
195 
196     public void setEncrypted(bool value)
197     {
198       fields["encrypted"] = value ? "true" : null;
199     }
200     
201     public void setEncrypted()
202     {
203       setEncrypted(true);
204     }
205     
206     public void setUserPassword(string pwd)
207     {
208       fields["user_pwd"] = pwd;
209     }
210     
211     public void setOwnerPassword(string pwd)
212     {
213       fields["owner_pwd"] = pwd;
214     }
215 
216     public void setNoPrint(bool value)
217     {
218       fields["no_print"] = value ? "true" : null;
219     }
220     
221     public void setNoPrint()
222     {
223       setNoPrint(true);
224     }
225     
226     public void setNoModify(bool value)
227     {
228       fields["no_modify"] = value ? "true" : null;
229     }
230 
231     public void setNoModify()
232     {
233       setNoModify(true);
234     }
235 
236     public void setNoCopy(bool value)
237     {
238       fields["no_copy"] = value ? "true" : null;
239     }
240 
241     public void setNoCopy()
242     {
243       setNoCopy(true);
244     }
245 
246     // constants for setPageLayout()
247     static public int SINGLE_PAGE = 1;
248     static public int CONTINUOUS = 2;
249     static public int CONTINUOUS_FACING = 3;
250           
251     public void setPageLayout(int value)
252     {
253       Debug.Assert(value > 0 && value <= 3);
254       fields["page_layout"] = value.ToString();
255     }
256 
257     // constants for setPageMode()
258     static public int NONE_VISIBLE = 1;
259     static public int THUMBNAILS_VISIBLE = 2;
260     static public int FULLSCREEN = 3;
261           
262     public void setPageMode(int value)
263     {
264       Debug.Assert(value > 0 && value <= 3);
265       fields["page_mode"] = value.ToString();
266     }
267 
268     public void setFooterText(string value) {
269         fields["footer_text"] = value;
270     }
271     
272     public void enableImages() {
273         enableImages(true);
274     }
275 
276     public void enableImages(bool value) {
277         fields["no_images"] = value ? null : "true";
278     }
279 
280     public void enableBackgrounds() {
281         enableBackgrounds(true);
282     }
283     
284     public void enableBackgrounds(bool value) {
285         fields["no_backgrounds"] = value ? null : "true";
286     }
287 
288     public void setHtmlZoom(float value) {
289         fields["html_zoom"] = value.ToString();
290     }
291 
292     public void enableJavaScript() {
293         enableJavaScript(true);
294     }
295     
296     public void enableJavaScript(bool value) {
297         fields["no_javascript"] = value ? null : "true";
298     }
299 
300     public void enableHyperlinks() {
301         enableHyperlinks(true);
302     }
303 
304     public void enableHyperlinks(bool value) {
305         fields["no_hyperlinks"] = value ? null : "true";
306     }
307     
308     public void setDefaultTextEncoding(string value) {
309         fields["text_encoding"] = value;
310     }
311 
312     public void usePrintMedia() {
313         usePrintMedia(true);
314     }
315     
316     public void usePrintMedia(bool value) {
317         fields["use_print_media"] = value ? "true" : null;
318     }
319 
320     public void setMaxPages(int value) {
321         fields["max_pages"] = value.ToString();
322     }
323 
324     public void enablePdfcrowdLogo() {
325         enablePdfcrowdLogo(true);
326     }
327 
328     public void enablePdfcrowdLogo(bool value) {
329         fields["pdfcrowd_logo"] = value ? "true" : null;
330     }
331 
332     // constants for setInitialPdfZoomType()
333     static public int FIT_WIDTH = 1;
334     static public int FIT_HEIGHT = 2;
335     static public int FIT_PAGE = 3;
336           
337     public void setInitialPdfZoomType(int value) {
338         Debug.Assert(value>0 && value<=3);
339         fields["initial_pdf_zoom_type"] = value.ToString();
340     }
341     
342     public void setInitialPdfExactZoom(float value) {
343         fields["initial_pdf_zoom_type"] = "4";
344         fields["initial_pdf_zoom"] = value.ToString();
345     }
346           
347     public void setAuthor(string value) {
348         fields["author"] = value;
349     }
350 
351     public void setFailOnNon200(bool value) {
352         fields["fail_on_non200"] = value ? "true" : null;
353     }
354 
355     public void setPdfScalingFactor(float value) {
356         fields["pdf_scaling_factor"] = value.ToString();
357     }
358 
359     public void setFooterHtml(string value) {
360         fields["footer_html"] = value;
361     }
362         
363     public void setFooterUrl(string value) {
364         fields["footer_url"] = value;
365     }
366         
367     public void setHeaderHtml(string value) {
368         fields["header_html"] = value;
369     }
370         
371     public void setHeaderUrl(string value) {
372         fields["header_url"] = value;
373     }
374 
375     public void setPageBackgroundColor(string value) {
376         fields["page_background_color"] = value;
377     }
378 
379 
380 
381           
382     public void setTransparentBackground() {
383         setTransparentBackground(true);
384     }
385     
386     public void setTransparentBackground(bool val) {
387         fields["transparent_background"] = val ? "true" : null;
388     }
389 
390 
391     public void setPageNumberingOffset(int value) {
392         fields["page_numbering_offset"] = value.ToString();
393     }
394 
395     public void setHeaderFooterPageExcludeList(string value) {
396         fields["header_footer_page_exclude_list"] = value;
397     }
398         
399     public void setWatermark(string url, float offset_x, float offset_y) {
400         fields["watermark_url"] = url;
401         fields["watermark_offset_x"] = offset_x.ToString();
402         fields["watermark_offset_y"] = offset_y.ToString();
403     }
404 
405     public void setWatermark(string url, string offset_x, string offset_y) {
406         fields["watermark_url"] = url;
407         fields["watermark_offset_x"] = offset_x;
408         fields["watermark_offset_y"] = offset_y;
409     }
410     
411     public void setWatermarkRotation(double angle) {
412         fields["watermark_rotation"] = angle.ToString();
413     }
414 
415     public void setWatermarkInBackground() {
416             setWatermarkInBackground(true);
417     }
418     
419     public void setWatermarkInBackground(bool val) {
420         fields["watermark_in_background"] = val ? "true" : null;
421     }
422           
423           
424 
425 
426     // ---------------------------------------------------------------------------
427     //
428     //                        Private stuff
429     //
430 
431     static string API_SELECTOR_BASE = "/api/";
432 
433     public string HOST = "pdfcrowd.com";
434     static public int HTTP_PORT = 80;
435     static public int HTTPS_PORT = 443;
436 
437     StringDictionary fields = new StringDictionary();
438     string api_uri;
439 
440           
441     private void convert(Stream out_stream, string method, string src)
442     {
443       string uri = String.Format("{0}pdf/convert/{1}/", api_uri, method);
444       call_api(uri, out_stream, src);
445     }
446     
447     private static void CopyStream(Stream input, Stream output)
448     {
449       byte[] buffer = new byte[32768];
450       while(true)
451         {
452           int read = input.Read(buffer, 0, buffer.Length);
453           if(read <= 0)
454             return;
455           output.Write(buffer, 0, read);
456         }
457     }
458     
459 
460     private void call_api(string uri, Stream out_stream, string src)
461     {
462       StringDictionary extra_data = new StringDictionary();
463       if (src != null)
464       {
465           extra_data["src"] = src;
466       }
467       string data = encode_post_data(extra_data);
468       do_request(uri, out_stream, data, "application/x-www-form-urlencoded");
469     }
470 
471     private static void do_request(string uri, Stream out_stream, object data, string content_type)
472     {
473       WebRequest request = WebRequest.Create(uri);
474       request.Method = "POST";
475      
476       byte[] byteArray;
477       if ((data is byte[]))
478       {
479           byteArray = (byte[])data;
480       }
481       else
482       {
483           byteArray = Encoding.UTF8.GetBytes((string)data);
484       }
485       request.ContentType = content_type;
486       request.ContentLength = byteArray.Length;
487       try
488       {
489           using(Stream dataStream = request.GetRequestStream())
490           {
491               dataStream.Write(byteArray, 0, byteArray.Length);
492           }
493           
494           // Get the response.
495           using(HttpWebResponse response = (HttpWebResponse) request.GetResponse())
496           {
497               if(response.StatusCode == HttpStatusCode.OK)
498               {
499                   // Get the stream containing content returned by the server.
500                   using(Stream dataStream = response.GetResponseStream())
501                   {
502                       CopyStream(dataStream, out_stream);
503                       out_stream.Position = 0;
504                   }
505               }
506               else
507               {
508                    throw new Error(response.StatusDescription, response.StatusCode);
509               }
510           }
511       }
512       catch(WebException why)
513       {
514           if (why.Status == WebExceptionStatus.ProtocolError)
515           {
516               HttpWebResponse response = (HttpWebResponse)why.Response;
517 
518               MemoryStream stream = new MemoryStream();
519               CopyStream(response.GetResponseStream(), stream);
520               stream.Position = 0;
521               string err = read_stream(stream);
522               throw new Error(err, response.StatusCode);
523           } else {
524               string innerException = "";
525               if (why.InnerException != null)
526               {
527                   innerException = "\n" + why.InnerException.Message;
528               }
529               throw new Error(why.Message + innerException, HttpStatusCode.Unused);
530           }
531       }
532     }
533     
534     private string encode_post_data(StringDictionary extra_data)
535     {
536       StringDictionary data = new StringDictionary();
537       if(extra_data != null)
538       {
539           foreach(DictionaryEntry entry in extra_data)
540           {
541               if(entry.Value != null)
542               {
543                   data.Add(entry.Key.ToString(), entry.Value.ToString());
544               }
545           }
546       }
547       
548       foreach(DictionaryEntry entry in fields)
549       {
550           if(entry.Value != null)
551           {
552               data.Add(entry.Key.ToString(), entry.Value.ToString());
553           }
554       }
555       string result = "";
556       int i = 0;
557       foreach(DictionaryEntry entry in data)
558       {
559           result += HttpUtility.UrlEncode(entry.Key.ToString()) + "=" + HttpUtility.UrlEncode(entry.Value.ToString());
560           if(i < data.Count)
561           {
562               result += "&";
563           }
564       }
565       return result.Substring(0, result.Length - 1);
566     }
567     
568     private static string boundary = "----------ThIs_Is_tHe_bOUnDary_$";
569     private static string multipart_content_type = "multipart/form-data; boundary=" + boundary;
570     private static string new_line = "\r\n";
571     
572     private static string get_mime_type(string fileName)
573     {
574       string mimeType = "application/octet-stream";
575       string ext = System.IO.Path.GetExtension(fileName).ToLower();
576       Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext);
577       if(regKey != null && regKey.GetValue("Content Type") != null)
578         mimeType = regKey.GetValue("Content Type").ToString();
579       return mimeType;
580     }
581     
582     private byte[] encode_multipart_post_data(string filename)
583     {
584       MemoryStream memw = new MemoryStream();
585       BinaryWriter retval = new BinaryWriter(memw);
586       UTF8Encoding utf8 = new UTF8Encoding();
587 
588       string result = "";
589       foreach(DictionaryEntry entry in fields)
590         {
591           if(entry.Value != null)
592             {
593               result += "--" + boundary + new_line;
594               result += String.Format("Content-Disposition: form-data; name=\"{0}\"", entry.Key) + new_line;
595               result += new_line;
596               result += entry.Value.ToString() + new_line;
597             }
598         }
599       // filename
600       result += "--" + boundary + new_line;
601       result += String.Format("Content-Disposition: form-data; name=\"src\"; filename=\"{0}\"", filename) + new_line;
602       result += "Content-Type: " + get_mime_type(filename) + new_line;
603       result += new_line;
604       retval.Write(utf8.GetBytes(result));
605       // filename contents
606       using(FileStream fin = File.OpenRead(filename))
607         {
608           byte[] b = new byte[8192];
609           int r;
610           while ((r = fin.Read(b, 0, b.Length)) > 0)
611             retval.Write(b, 0, r);
612         }
613       // finalize
614       result = new_line + "--" + boundary + "--" + new_line;
615       result += new_line;
616 
617       retval.Write(utf8.GetBytes(result));
618       retval.Flush();
619       return memw.ToArray();
620     }
621 
622     private static string read_stream(Stream stream)
623     {
624       using(StreamReader reader = new StreamReader(stream, Encoding.UTF8))
625       {
626           return reader.ReadToEnd();
627       }
628     }
629 
630     private void post_multipart(string fpath, Stream out_stream)
631     {
632       byte[] data = encode_multipart_post_data(fpath);
633       do_request(api_uri + "pdf/convert/html/", out_stream, data, multipart_content_type);
634     }
635     
636 
637   }
638 }