C#: Send text to a pastebin (HttpWebRequest POST example)
I’m working on a small application that hooks into the clipboard monitor chain and displays a list of options whenever text is saved to the clipbaord. One of the options I wanted was to be able to send data to pastebin.com, a popular text/code sharing service. This is a relatively mundane task, faking the postdata for a webpage, and sending the requests as a browser. There were some hicups though, mostly with Finding the redirect URL using HttpWebRequest/HttpWebResponse.
A little background:
HttpWebRequest and HttpWebResponse live in the System.Net namespace, and provide the ability to quickly send HTTP requests to a webserver. This is what a simple GET request would look like:
try { HttpWebRequest request = (HttpWebRequest) WebRequest.Create("http://davux.pastebin.com/pastebin.php"); HttpWebResponse res =(HttpWebResponse) request.GetResponse(); if (res.StatusCode == HttpStatusCode.OK) { StreamReader reader = new StreamReader(res.GetResponseStream()); Console.WriteLine(reader.ReadToEnd()); } else { // handle errors } res.Close(); } catch (Exception ex) { Console.WriteLine("Error: " + ex.Message); }
Note: For most simple tasks, it is wise to use System.Net.WebClient, which is not suitable for this task, because it does not expose the ability to disable automatic redirection.
To send new data to pastebin, it needs to be sent via HTTP POST. Using Firefox LiveHTTPHeaders, I determined what string needs to be sent in order to create a new entry. This can also be determined by reading the source of the page, and looking at each of the fields contained in the <form> block.
string post = "&parent_pid=&format=text&code2=" + code_text_to_send + "&poster=" + poster_name + "&paste=Send&expiry=" + expiry + "&email=";
- code_text_to_send – The data which should be used to create a new page.
- poster_name – The author of the post
- expiry – How long the data should be retained for. Options are ‘d’ for one day, ‘m’ for one month, and ‘f’ for indefinitely.
Note: Make sure to URLEncode each field that is sent!
After further examination of the headers and data sent back, I decided that the best way to extract the link was to catch the HTTP 302 Document Found response.
HTTP/1.x 302 Found Date: Thu, 08 May 2008 01:06:08 GMT Server: Apache/1.3.33 (Debian GNU/Linux) mod_python/2.7.10 Python/2.3.4 PHP/4.3.10-22 mod_perl/1.29 X-Powered-By: PHP/4.3.10-22 Location: http://davux.pastebin.com/m10a794d6 Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: text/html; charset=iso-8859-1
HttpWebRequest, by default, has AllowAutoRedirect set to true, which means that, internally, it will resolve this message, and fetch the new URL. This extra operation is needless in this circumstance, so it is best to disable it and extract the URL from the header. The headers associated with each request or response are found in the Headers object for each class. We wish to look at the Location field to find our URL.
C# WebClient HTTP POST Example:
try { HttpWebRequest request = (HttpWebRequest) WebRequest.Create("http://davux.pastebin.com/pastebin.php"); request.AllowAutoRedirect = false; request.Method = "POST"; string post = "&parent_pid=&format=text&code2=" + HttpUtility.UrlEncode(text) + "&poster=Dave&paste=Send&expiry=m&email="; byte[] data = System.Text.Encoding.ASCII.GetBytes(post); request.ContentType = "application/x-www-form-urlencoded"; request.ContentLength = data.Length; Stream response = request.GetRequestStream(); response.Write(data,0,data.Length); response.Close(); HttpWebResponse res =(HttpWebResponse) request.GetResponse(); res.Close(); // note that there is no need to hook up a StreamReader and // look at the response data, since it is of no need if (res.StatusCode == HttpStatusCode.Found) { Console.WriteLine(res.Headers["location"]); } else { Console.WriteLine("Error"); } } catch (Exception ex) { Console.WriteLine("Error: " + ex.Message); }
(Some error checking and extra code have been removed for the sake of clarity)
The values for expiry and author have been hard-coded in order to save space. This basic example will create a new Pastebin entry on my not so private pastebin, and print the URL of the entry to the console. If there is an error, it will print the exception message. If the HTTP code returned is not 302/Found, it will print a generic error. (If the server is not returning a 302 for this request, there is nothing codewise that can be fixed, and thus the only option for error is generic.)
Comments
4 Comments on C#: Send text to a pastebin (HttpWebRequest POST example)
-
Soroush on
Sun, 18th May 2008 1:01 pm
-
Dave on
Sun, 18th May 2008 1:11 pm
-
Soroush on
Wed, 21st May 2008 4:58 am
-
Soroush on
Sat, 24th May 2008 1:31 am
Thanks for your nice post.
I write this program as you do. but when i check the site http://davux.pastebin.com/pastebin.php
i don’t see anything that shows i did this. I mean no post are added to this site… please help me
Hi Soroush -
Are you getting a URL back in the location field of the header?
I see someone just added something to that bin a few minutes ago, perhaps you got it fixed.
Thanks for your attention. No it was not me.I still have my previous problem. I think it’s better you to see my code, here it is:
string text = “Soroush”;
string post = “&parent_pid=&format=text&code2=”
+ HttpUtility.UrlEncode(text) + “&poster=Soroush&paste=Send&expiry=m&email=”;
byte[] data = System.Text.Encoding.ASCII.GetBytes(post);
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(“http://davux.pastebin.com/pastebin.php”);
request.AllowAutoRedirect = false;
request.Method = “POST”;
request.ContentType = “application/x-www-form-urlencoded”;
request.ContentLength = data.Length;
Stream response = request.GetRequestStream();
response.Write(data, 0, data.Length);
response.Close();
HttpWebResponse res = (HttpWebResponse)request.GetResponse();
res.Close();
if (res.StatusCode == HttpStatusCode.Found)
{
richTextBox1.Text += res.Headers["location"];
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
hey Dave why don’t you answer me?? please…
