summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Arnott <andrewarnott@gmail.com>2009-03-21 14:10:41 -0700
committerAndrew Arnott <andrewarnott@gmail.com>2009-03-21 14:10:41 -0700
commitec8e3b27155297b790cadcfdebbe24fa2cbfa639 (patch)
treebd710d4964741fddad097b66e7b5e0b6eeca8b1b
parent4197cf4144223397b3c1aa03eb136b34820c3684 (diff)
downloadDotNetOpenAuth-ec8e3b27155297b790cadcfdebbe24fa2cbfa639.zip
DotNetOpenAuth-ec8e3b27155297b790cadcfdebbe24fa2cbfa639.tar.gz
DotNetOpenAuth-ec8e3b27155297b790cadcfdebbe24fa2cbfa639.tar.bz2
Added Blogger posting OAuth sample.
-rw-r--r--samples/ConsumerWpf/MainWindow.xaml41
-rw-r--r--samples/ConsumerWpf/MainWindow.xaml.cs15
-rw-r--r--samples/DotNetOpenAuth.ApplicationBlock/GoogleConsumer.cs55
-rw-r--r--samples/DotNetOpenAuth.ApplicationBlock/Util.cs49
4 files changed, 150 insertions, 10 deletions
diff --git a/samples/ConsumerWpf/MainWindow.xaml b/samples/ConsumerWpf/MainWindow.xaml
index 4fdf4e6..a3794c8 100644
--- a/samples/ConsumerWpf/MainWindow.xaml
+++ b/samples/ConsumerWpf/MainWindow.xaml
@@ -1,8 +1,8 @@
<Window x:Class="DotNetOpenAuth.Samples.ConsumerWpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- Title="DotNetOpenAuth Consumer (sample)" Height="248" Width="429">
- <Grid>
+ Title="DotNetOpenAuth Consumer (sample)" Height="400" Width="442">
+ <Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
@@ -30,11 +30,36 @@
</Hyperlink>
</TextBlock>
</Label>
- <Grid Grid.ColumnSpan="2" Grid.Row="4" Name="contactsGrid">
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="Auto" />
- <ColumnDefinition Width="Auto" />
- </Grid.ColumnDefinitions>
- </Grid>
+ <TabControl Grid.ColumnSpan="2" Grid.Row="4" Name="tabControl1" Margin="0,10,0,0">
+ <TabItem Header="Gmail Contacts" Name="gmailContactsTab">
+ <Grid Name="contactsGrid">
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto" />
+ <ColumnDefinition Width="Auto" />
+ </Grid.ColumnDefinitions>
+ </Grid>
+ </TabItem>
+ <TabItem Header="Blogger" Name="bloggerTab">
+ <Grid>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto" />
+ <ColumnDefinition Width="*" />
+ </Grid.ColumnDefinitions>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ </Grid.RowDefinitions>
+ <Label>Blog URL</Label>
+ <TextBox Grid.Column="1" x:Name="blogUrlBox"/>
+ <Label Grid.Row="1">Title</Label>
+ <TextBox Grid.Row="1" Grid.Column="1" x:Name="postTitleBox">OAuth Rocks!</TextBox>
+ <Label Grid.Row="2">Body</Label>
+ <TextBox Grid.Row="2" Grid.Column="1" x:Name="postBodyBox" AcceptsReturn="True" AcceptsTab="True" AutoWordSelection="True" TextWrapping="WrapWithOverflow">&lt;p xmlns="http://www.w3.org/1999/xhtml"&gt;Oauth is cool&lt;/p&gt;</TextBox>
+ <Button x:Name="postButton" Grid.Row="3" Grid.Column="1" Click="postButton_Click" IsEnabled="False">Post</Button>
+ </Grid>
+ </TabItem>
+ </TabControl>
</Grid>
</Window>
diff --git a/samples/ConsumerWpf/MainWindow.xaml.cs b/samples/ConsumerWpf/MainWindow.xaml.cs
index bcaae6f..ea3ea39 100644
--- a/samples/ConsumerWpf/MainWindow.xaml.cs
+++ b/samples/ConsumerWpf/MainWindow.xaml.cs
@@ -13,7 +13,9 @@
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
+ using System.Xml;
using System.Xml.Linq;
+ using System.Xml.XPath;
using DotNetOpenAuth;
using DotNetOpenAuth.ApplicationBlock;
using DotNetOpenAuth.Messaging;
@@ -27,6 +29,7 @@
private InMemoryTokenManager tokenManager = new InMemoryTokenManager();
private DesktopConsumer google;
private string requestToken;
+ private string accessToken;
public MainWindow() {
InitializeComponent();
@@ -43,18 +46,23 @@
this.Cursor = Cursors.Wait;
beginAuthorizationButton.IsEnabled = false;
ThreadPool.QueueUserWorkItem(delegate(object state) {
- Uri browserAuthorizationLocation = GoogleConsumer.RequestAuthorization(this.google, GoogleConsumer.Applications.Contacts, out this.requestToken);
+ Uri browserAuthorizationLocation = GoogleConsumer.RequestAuthorization(
+ this.google,
+ GoogleConsumer.Applications.Contacts | GoogleConsumer.Applications.Blogger,
+ out this.requestToken);
System.Diagnostics.Process.Start(browserAuthorizationLocation.AbsoluteUri);
this.Dispatcher.BeginInvoke(new Action(() => {
this.Cursor = original;
beginAuthorizationButton.IsEnabled = true;
completeAuthorizationButton.IsEnabled = true;
+ postButton.IsEnabled = true;
}));
});
}
private void completeAuthorizationButton_Click(object sender, RoutedEventArgs e) {
var grantedAccess = this.google.ProcessUserAuthorization(this.requestToken);
+ this.accessToken = grantedAccess.AccessToken;
XDocument contactsDocument = GoogleConsumer.GetContacts(this.google, grantedAccess.AccessToken);
var contacts = from entry in contactsDocument.Root.Elements(XName.Get("entry", "http://www.w3.org/2005/Atom"))
select new {
@@ -73,5 +81,10 @@
contactsGrid.Children.Add(email);
}
}
+
+ private void postButton_Click(object sender, RoutedEventArgs e) {
+ XElement postBodyXml = XElement.Parse(postBodyBox.Text);
+ GoogleConsumer.PostBlogEntry(this.google, this.accessToken, blogUrlBox.Text, postTitleBox.Text, postBodyXml);
+ }
}
}
diff --git a/samples/DotNetOpenAuth.ApplicationBlock/GoogleConsumer.cs b/samples/DotNetOpenAuth.ApplicationBlock/GoogleConsumer.cs
index 2206fff..c6f2b89 100644
--- a/samples/DotNetOpenAuth.ApplicationBlock/GoogleConsumer.cs
+++ b/samples/DotNetOpenAuth.ApplicationBlock/GoogleConsumer.cs
@@ -7,7 +7,13 @@
namespace DotNetOpenAuth.ApplicationBlock {
using System;
using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.IO;
using System.Linq;
+ using System.Net;
+ using System.Text;
+ using System.Text.RegularExpressions;
+ using System.Xml;
using System.Xml.Linq;
using DotNetOpenAuth.Messaging;
using DotNetOpenAuth.OAuth;
@@ -33,6 +39,7 @@ namespace DotNetOpenAuth.ApplicationBlock {
private static readonly Dictionary<Applications, string> DataScopeUris = new Dictionary<Applications, string> {
{ Applications.Contacts, "http://www.google.com/m8/feeds/" },
{ Applications.Calendar, "http://www.google.com/calendar/feeds/" },
+ { Applications.Blogger, "http://www.blogger.com/feeds" },
};
/// <summary>
@@ -54,6 +61,11 @@ namespace DotNetOpenAuth.ApplicationBlock {
/// Appointments in Google Calendar.
/// </summary>
Calendar = 0x2,
+
+ /// <summary>
+ /// Blog post authoring.
+ /// </summary>
+ Blogger = 0x4,
}
/// <summary>
@@ -134,6 +146,49 @@ namespace DotNetOpenAuth.ApplicationBlock {
return result;
}
+ public static void PostBlogEntry(ConsumerBase consumer, string accessToken, string blogUrl, string title, XElement body) {
+ string feedUrl;
+ var getBlogHome = WebRequest.Create(blogUrl);
+ using (var blogHomeResponse = getBlogHome.GetResponse()) {
+ using (StreamReader sr = new StreamReader(blogHomeResponse.GetResponseStream())) {
+ string homePageHtml = sr.ReadToEnd();
+ Match m = Regex.Match(homePageHtml, @"http://www.blogger.com/feeds/\d+/posts/default");
+ Debug.Assert(m.Success, "Posting operation failed.");
+ feedUrl = m.Value;
+ }
+ }
+ const string Atom = "http://www.w3.org/2005/Atom";
+ XElement entry = new XElement(
+ XName.Get("entry", Atom),
+ new XElement(XName.Get("title", Atom), new XAttribute("type", "text"), title),
+ new XElement(XName.Get("content", Atom), new XAttribute("type", "xhtml"), body),
+ new XElement(XName.Get("category", Atom), new XAttribute("scheme", "http://www.blogger.com/atom/ns#"), new XAttribute("term", "oauthdemo")));
+
+ MemoryStream ms = new MemoryStream();
+ XmlWriterSettings xws = new XmlWriterSettings() {
+ Encoding = Encoding.UTF8,
+ };
+ XmlWriter xw = XmlWriter.Create(ms, xws);
+ entry.WriteTo(xw);
+ xw.Flush();
+
+ WebRequest request = consumer.PrepareAuthorizedRequest(new MessageReceivingEndpoint(feedUrl, HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest), accessToken);
+ request.ContentType = "application/atom+xml";
+ request.Method = "POST";
+ request.ContentLength = ms.Length;
+ ms.Seek(0, SeekOrigin.Begin);
+ using (Stream requestStream = request.GetRequestStream()) {
+ ms.CopyTo(requestStream);
+ }
+ using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {
+ if (response.StatusCode == HttpStatusCode.Created) {
+ // Success
+ } else {
+ // Error!
+ }
+ }
+ }
+
/// <summary>
/// Gets the scope URI in Google's format.
/// </summary>
diff --git a/samples/DotNetOpenAuth.ApplicationBlock/Util.cs b/samples/DotNetOpenAuth.ApplicationBlock/Util.cs
index 5001e2e..ea7da97 100644
--- a/samples/DotNetOpenAuth.ApplicationBlock/Util.cs
+++ b/samples/DotNetOpenAuth.ApplicationBlock/Util.cs
@@ -1,9 +1,10 @@
namespace DotNetOpenAuth.ApplicationBlock {
using System;
using System.Collections.Generic;
+ using System.IO;
using DotNetOpenAuth.Messaging;
- internal class Util {
+ internal static class Util {
/// <summary>
/// Enumerates through the individual set bits in a flag enum.
/// </summary>
@@ -25,5 +26,51 @@
Uri callback = MessagingUtilities.GetRequestUrlFromContext().StripQueryArgumentsWithPrefix("oauth_");
return callback;
}
+
+ /// <summary>
+ /// Copies the contents of one stream to another.
+ /// </summary>
+ /// <param name="copyFrom">The stream to copy from, at the position where copying should begin.</param>
+ /// <param name="copyTo">The stream to copy to, at the position where bytes should be written.</param>
+ /// <returns>The total number of bytes copied.</returns>
+ /// <remarks>
+ /// Copying begins at the streams' current positions.
+ /// The positions are NOT reset after copying is complete.
+ /// </remarks>
+ internal static int CopyTo(this Stream copyFrom, Stream copyTo) {
+ return CopyTo(copyFrom, copyTo, int.MaxValue);
+ }
+
+ /// <summary>
+ /// Copies the contents of one stream to another.
+ /// </summary>
+ /// <param name="copyFrom">The stream to copy from, at the position where copying should begin.</param>
+ /// <param name="copyTo">The stream to copy to, at the position where bytes should be written.</param>
+ /// <param name="maximumBytesToCopy">The maximum bytes to copy.</param>
+ /// <returns>The total number of bytes copied.</returns>
+ /// <remarks>
+ /// Copying begins at the streams' current positions.
+ /// The positions are NOT reset after copying is complete.
+ /// </remarks>
+ internal static int CopyTo(this Stream copyFrom, Stream copyTo, int maximumBytesToCopy) {
+ if (copyFrom == null) {
+ throw new ArgumentNullException("copyFrom");
+ }
+ if (copyTo == null) {
+ throw new ArgumentNullException("copyTo");
+ }
+
+ byte[] buffer = new byte[1024];
+ int readBytes;
+ int totalCopiedBytes = 0;
+ while ((readBytes = copyFrom.Read(buffer, 0, Math.Min(1024, maximumBytesToCopy))) > 0) {
+ int writeBytes = Math.Min(maximumBytesToCopy, readBytes);
+ copyTo.Write(buffer, 0, writeBytes);
+ totalCopiedBytes += writeBytes;
+ maximumBytesToCopy -= writeBytes;
+ }
+
+ return totalCopiedBytes;
+ }
}
}