Merge lp:~mandel/ubuntuone-windows-installer/refactor_sso into lp:ubuntuone-windows-installer/beta

Proposed by Manuel de la Peña
Status: Merged
Approved by: Rick McBride
Approved revision: 88
Merged at revision: 90
Proposed branch: lp:~mandel/ubuntuone-windows-installer/refactor_sso
Merge into: lp:ubuntuone-windows-installer/beta
Prerequisite: lp:~mandel/ubuntuone-windows-installer/re_enable_keyring_tests
Diff against target: 2731 lines (+2118/-397)
21 files modified
src/Canonical.Ubuntu.SSO.Tests/Canonical.Ubuntu.SSO.Tests.csproj (+7/-0)
src/Canonical.Ubuntu.SSO.Tests/ColonSeparatedSSOCredentialsEncoderFixture.cs (+69/-0)
src/Canonical.Ubuntu.SSO.Tests/JsonSSOCredentialsEncoderFixture.cs (+29/-0)
src/Canonical.Ubuntu.SSO.Tests/SSOLoginProcessorFixture.cs (+98/-0)
src/Canonical.Ubuntu.SSO/Canonical.Ubuntu.SSO.csproj (+11/-1)
src/Canonical.Ubuntu.SSO/ColonSeparatedSSOCredentialsEncoder.cs (+60/-0)
src/Canonical.Ubuntu.SSO/DPAPIDataProtector.cs (+0/-1)
src/Canonical.Ubuntu.SSO/IOAuth.cs (+122/-0)
src/Canonical.Ubuntu.SSO/ISSOCredentialsEncoder.cs (+46/-0)
src/Canonical.Ubuntu.SSO/JsonSSOCredentialsEncoder.cs (+82/-0)
src/Canonical.Ubuntu.SSO/OAuth.cs (+391/-0)
src/Canonical.Ubuntu.SSO/OAuthBase.cs (+0/-358)
src/Canonical.Ubuntu.SSO/SSOException.cs (+57/-0)
src/Canonical.Ubuntu.SSO/SSOLoginException.cs (+57/-0)
src/Canonical.Ubuntu.SSO/SSOLoginProcessor.cs (+154/-1)
src/Canonical.UbuntuOne.Client/Notification/NotificationIconPresenter.cs (+25/-36)
src/Canonical.UbuntuOne.Common/Canonical.UbuntuOne.Common.csproj (+4/-0)
src/Canonical.UbuntuOne.Common/Net/HttpWebRequest.cs (+505/-0)
src/Canonical.UbuntuOne.Common/Net/HttpWebRequestFactory.cs (+59/-0)
src/Canonical.UbuntuOne.Common/Net/IHttpWebRequest.cs (+297/-0)
src/Canonical.UbuntuOne.Common/Net/IHttpWebRequestFactory.cs (+45/-0)
To merge this branch: bzr merge lp:~mandel/ubuntuone-windows-installer/refactor_sso
Reviewer Review Type Date Requested Status
Rick McBride (community) Approve
John Lenton (community) Approve
Review via email: mp+37577@code.launchpad.net

Description of the change

SSO has been refactored to make it more testeable and robust.

To post a comment you must log in.
Revision history for this message
John Lenton (chipaca) :
review: Approve
Revision history for this message
Rick McBride (rmcbride) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/Canonical.Ubuntu.SSO.Tests/Canonical.Ubuntu.SSO.Tests.csproj'
2--- src/Canonical.Ubuntu.SSO.Tests/Canonical.Ubuntu.SSO.Tests.csproj 2010-10-05 09:58:34 +0000
3+++ src/Canonical.Ubuntu.SSO.Tests/Canonical.Ubuntu.SSO.Tests.csproj 2010-10-05 09:58:35 +0000
4@@ -48,14 +48,21 @@
5 <Reference Include="System.Xml" />
6 </ItemGroup>
7 <ItemGroup>
8+ <Compile Include="ColonSeparatedSSOCredentialsEncoderFixture.cs" />
9+ <Compile Include="JsonSSOCredentialsEncoderFixture.cs" />
10 <Compile Include="KeyringFixture.cs" />
11 <Compile Include="Properties\AssemblyInfo.cs" />
12+ <Compile Include="SSOLoginProcessorFixture.cs" />
13 </ItemGroup>
14 <ItemGroup>
15 <ProjectReference Include="..\Canonical.Ubuntu.SSO\Canonical.Ubuntu.SSO.csproj">
16 <Project>{9460A771-2589-45DA-9618-9FE8BB7D16E8}</Project>
17 <Name>Canonical.Ubuntu.SSO</Name>
18 </ProjectReference>
19+ <ProjectReference Include="..\Canonical.UbuntuOne.Common\Canonical.UbuntuOne.Common.csproj">
20+ <Project>{11353FF8-8E5A-488E-9CB1-873DADD232B9}</Project>
21+ <Name>Canonical.UbuntuOne.Common</Name>
22+ </ProjectReference>
23 </ItemGroup>
24 <ItemGroup>
25 <Folder Include="Service\" />
26
27=== added file 'src/Canonical.Ubuntu.SSO.Tests/ColonSeparatedSSOCredentialsEncoderFixture.cs'
28--- src/Canonical.Ubuntu.SSO.Tests/ColonSeparatedSSOCredentialsEncoderFixture.cs 1970-01-01 00:00:00 +0000
29+++ src/Canonical.Ubuntu.SSO.Tests/ColonSeparatedSSOCredentialsEncoderFixture.cs 2010-10-05 09:58:35 +0000
30@@ -0,0 +1,69 @@
31+/* Copyright 2010 Canonical Ltd.
32+ *
33+ * This file is part of UbuntuOne on Windows.
34+ *
35+ * UbuntuOne on Windows is free software: you can redistribute it and/or modify
36+ * it under the terms of the GNU Lesser General Public License version
37+ * as published by the Free Software Foundation.
38+ *
39+ * Ubuntu One on Windows is distributed in the hope that it will be useful,
40+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
41+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
42+ * GNU Lesser General Public License for more details.
43+ *
44+ * You should have received a copy of the GNU Lesser General Public License
45+ * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
46+ *
47+ * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
48+ */
49+using NUnit.Framework;
50+
51+namespace Canonical.Ubuntu.SSO.Tests
52+{
53+ [TestFixture]
54+ public class ColonSeparatedSSOCredentialsEncoderFixture
55+ {
56+ #region Variables
57+
58+ private ColonSeparatedSSOCredentialsEncoder _encoder;
59+
60+ #endregion
61+
62+ #region Setup & TearDown
63+
64+ [SetUp]
65+ public void Setup()
66+ {
67+ _encoder = new ColonSeparatedSSOCredentialsEncoder();
68+ }
69+ #endregion
70+
71+ #region Tests
72+
73+ [TestCase("firstToken:firstTokenSecret:firstConsumer:firstConsumerSecret", "firstToken", "firstTokenSecret", "firstConsumer", "firstConsumerSecret")]
74+ [TestCase("ad180jjd733klru7:hdhd0244k9j7ao03:dpf43f3p2l4k3l03:djr9rjt0jd78jf88%26", "ad180jjd733klru7", "hdhd0244k9j7ao03", "dpf43f3p2l4k3l03", "djr9rjt0jd78jf88%26")]
75+ public void EncodeTest(string expected, string token, string tokenSecret, string consumerKey, string consumerSecret)
76+ {
77+ Assert.AreEqual(expected, _encoder.Encode(token, tokenSecret, consumerKey, consumerSecret));
78+ }
79+
80+ [TestCase("firstToken:firstTokenSecret:firstConsumer:firstConsumerSecret", "firstToken", "firstTokenSecret", "firstConsumer", "firstConsumerSecret")]
81+ [TestCase("ad180jjd733klru7:hdhd0244k9j7ao03:dpf43f3p2l4k3l03:djr9rjt0jd78jf88%26", "ad180jjd733klru7", "hdhd0244k9j7ao03", "dpf43f3p2l4k3l03", "djr9rjt0jd78jf88%26")]
82+ public void DecodeTest(string secret, string expectedToken, string expectedTokenSecret, string expectedConsumerKey,
83+ string expectedConsumerSecret)
84+ {
85+ string token;
86+ string tokenSecret;
87+ string consumerKey;
88+ string consumerSecret;
89+ _encoder.Decode(secret, out token, out tokenSecret, out consumerKey, out consumerSecret);
90+ Assert.AreEqual(expectedToken, token);
91+ Assert.AreEqual(expectedTokenSecret, tokenSecret);
92+ Assert.AreEqual(expectedConsumerKey, consumerKey);
93+ Assert.AreEqual(expectedConsumerSecret, consumerSecret);
94+ }
95+
96+ #endregion
97+
98+ }
99+}
100
101=== added file 'src/Canonical.Ubuntu.SSO.Tests/JsonSSOCredentialsEncoderFixture.cs'
102--- src/Canonical.Ubuntu.SSO.Tests/JsonSSOCredentialsEncoderFixture.cs 1970-01-01 00:00:00 +0000
103+++ src/Canonical.Ubuntu.SSO.Tests/JsonSSOCredentialsEncoderFixture.cs 2010-10-05 09:58:35 +0000
104@@ -0,0 +1,29 @@
105+/* Copyright 2010 Canonical Ltd.
106+ *
107+ * This file is part of UbuntuOne on Windows.
108+ *
109+ * UbuntuOne on Windows is free software: you can redistribute it and/or modify
110+ * it under the terms of the GNU Lesser General Public License version
111+ * as published by the Free Software Foundation.
112+ *
113+ * Ubuntu One on Windows is distributed in the hope that it will be useful,
114+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
115+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
116+ * GNU Lesser General Public License for more details.
117+ *
118+ * You should have received a copy of the GNU Lesser General Public License
119+ * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
120+ *
121+ * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
122+ */
123+using System;
124+using System.Collections.Generic;
125+using System.Linq;
126+using System.Text;
127+
128+namespace Canonical.Ubuntu.SSO.Tests
129+{
130+ class JsonSSOCredentialsEncoderFixture
131+ {
132+ }
133+}
134
135=== added file 'src/Canonical.Ubuntu.SSO.Tests/SSOLoginProcessorFixture.cs'
136--- src/Canonical.Ubuntu.SSO.Tests/SSOLoginProcessorFixture.cs 1970-01-01 00:00:00 +0000
137+++ src/Canonical.Ubuntu.SSO.Tests/SSOLoginProcessorFixture.cs 2010-10-05 09:58:35 +0000
138@@ -0,0 +1,98 @@
139+/* Copyright 2010 Canonical Ltd.
140+ *
141+ * This file is part of UbuntuOne on Windows.
142+ *
143+ * UbuntuOne on Windows is free software: you can redistribute it and/or modify
144+ * it under the terms of the GNU Lesser General Public License version
145+ * as published by the Free Software Foundation.
146+ *
147+ * Ubuntu One on Windows is distributed in the hope that it will be useful,
148+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
149+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
150+ * GNU Lesser General Public License for more details.
151+ *
152+ * You should have received a copy of the GNU Lesser General Public License
153+ * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
154+ *
155+ * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
156+ */
157+using Canonical.Ubuntu.SSO.Service;
158+using Canonical.UbuntuOne.Common.Net;
159+using NUnit.Framework;
160+using Rhino.Mocks;
161+
162+namespace Canonical.Ubuntu.SSO.Tests
163+{
164+ [TestFixture]
165+ public class SSOLoginProcessorFixture
166+ {
167+ #region Variables
168+
169+ private MockRepository _mocks;
170+ private Authentications _auth;
171+ private IKeyring _keyring;
172+ private ISSOCredentialsEncoder _encode;
173+ private IOAuth _oauth;
174+ private IHttpWebRequestFactory _requestFactory;
175+ private IHttpWebRequest _request;
176+ private SSOLoginProcessor _processor;
177+
178+ #endregion
179+
180+ #region Setup
181+
182+ [SetUp]
183+ public void Setup()
184+ {
185+ _mocks = new MockRepository();
186+ _auth = _mocks.DynamicMock<Authentications>();
187+ _keyring = _mocks.DynamicMock<IKeyring>();
188+ _encode = _mocks.DynamicMock<ISSOCredentialsEncoder>();
189+ _oauth = _mocks.DynamicMock<IOAuth>();
190+ _requestFactory = _mocks.DynamicMock<IHttpWebRequestFactory>();
191+ _request = _mocks.DynamicMock<IHttpWebRequest>();
192+ _processor = new SSOLoginProcessor
193+ {
194+ Authentications = _auth,
195+ HttpWebRequestFactory = _requestFactory,
196+ Keyring = _keyring,
197+ OAuth = _oauth,
198+ SSOCredentialsEncoder = _encode
199+ };
200+ }
201+
202+ #endregion
203+
204+ #region Tests
205+
206+ [TestCase("manuel@canonical.com", "Passwd", "UbuntuOne")]
207+ [TestCase("mandel@themacaque.com", "Test", "Gwibber")]
208+ [ExpectedException(typeof(SSOLoginException))]
209+ public void LoginCredentialsExceptionTest(string email, string password, string tokenName)
210+ {
211+ Assert.Ignore("Not yet implemented");
212+ }
213+
214+ [Test]
215+ [ExpectedException(typeof(SSOLoginException))]
216+ public void LoginPingExceptionTest()
217+ {
218+ Assert.Ignore("Not yet implemented");
219+ }
220+
221+ [Test]
222+ public void LoginNoSecretTest()
223+ {
224+ Assert.Ignore("Not yet implemented");
225+ }
226+
227+ [Test]
228+ public void LoginSecretTest()
229+ {
230+ Assert.Ignore("Not yet implemented");
231+ }
232+
233+ #endregion
234+
235+ }
236+}
237
238=== modified file 'src/Canonical.Ubuntu.SSO/Canonical.Ubuntu.SSO.csproj'
239--- src/Canonical.Ubuntu.SSO/Canonical.Ubuntu.SSO.csproj 2010-10-05 09:58:34 +0000
240+++ src/Canonical.Ubuntu.SSO/Canonical.Ubuntu.SSO.csproj 2010-10-05 09:58:35 +0000
241@@ -35,6 +35,10 @@
242 <SpecificVersion>False</SpecificVersion>
243 <HintPath>..\..\lib\log4net\log4net.dll</HintPath>
244 </Reference>
245+ <Reference Include="Newtonsoft.Json, Version=3.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
246+ <SpecificVersion>False</SpecificVersion>
247+ <HintPath>..\..\lib\JsonNet\Newtonsoft.Json.dll</HintPath>
248+ </Reference>
249 <Reference Include="System" />
250 <Reference Include="System.Core">
251 <RequiredTargetFramework>3.5</RequiredTargetFramework>
252@@ -54,6 +58,7 @@
253 <Compile Include="..\Version.cs">
254 <Link>Properties\Version.cs</Link>
255 </Compile>
256+ <Compile Include="ColonSeparatedSSOCredentialsEncoder.cs" />
257 <Compile Include="CredentialsDeniedEventArgs.cs" />
258 <Compile Include="CredentialsErrorEventArgs.cs" />
259 <Compile Include="CredentialsFoundEventArgs.cs" />
260@@ -61,11 +66,14 @@
261 <Compile Include="IDataProtector.cs" />
262 <Compile Include="ILoginOrRegisterView.cs" />
263 <Compile Include="ILoginView.cs" />
264+ <Compile Include="IOAuth.cs" />
265 <Compile Include="IRegistryKey.cs" />
266+ <Compile Include="ISSOCredentialsEncoder.cs" />
267 <Compile Include="ISSOLoginProcessor.cs" />
268+ <Compile Include="JsonSSOCredentialsEncoder.cs" />
269 <Compile Include="Keyring.cs" />
270 <Compile Include="LoginCredentialsEventArgs.cs" />
271- <Compile Include="OAuthBase.cs" />
272+ <Compile Include="OAuth.cs" />
273 <Compile Include="RegistryKeyWrapper.cs" />
274 <Compile Include="Service\Account.cs" />
275 <Compile Include="Service\AccountDiff.cs" />
276@@ -109,6 +117,8 @@
277 <Compile Include="IKeyring.cs" />
278 <Compile Include="ISSOCredentialsProvider.cs" />
279 <Compile Include="Properties\AssemblyInfo.cs" />
280+ <Compile Include="SSOException.cs" />
281+ <Compile Include="SSOLoginException.cs" />
282 <Compile Include="SSOLoginProcessor.cs" />
283 </ItemGroup>
284 <ItemGroup>
285
286=== added file 'src/Canonical.Ubuntu.SSO/ColonSeparatedSSOCredentialsEncoder.cs'
287--- src/Canonical.Ubuntu.SSO/ColonSeparatedSSOCredentialsEncoder.cs 1970-01-01 00:00:00 +0000
288+++ src/Canonical.Ubuntu.SSO/ColonSeparatedSSOCredentialsEncoder.cs 2010-10-05 09:58:35 +0000
289@@ -0,0 +1,60 @@
290+/* Copyright 2010 Canonical Ltd.
291+ *
292+ * This file is part of UbuntuOne on Windows.
293+ *
294+ * UbuntuOne on Windows is free software: you can redistribute it and/or modify
295+ * it under the terms of the GNU Lesser General Public License version
296+ * as published by the Free Software Foundation.
297+ *
298+ * Ubuntu One on Windows is distributed in the hope that it will be useful,
299+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
300+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
301+ * GNU Lesser General Public License for more details.
302+ *
303+ * You should have received a copy of the GNU Lesser General Public License
304+ * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
305+ *
306+ * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
307+ */
308+namespace Canonical.Ubuntu.SSO
309+{
310+ /// <summary>
311+ /// Encode implementation that encodes the oauth token using colons as separators.
312+ /// </summary>
313+ public class ColonSeparatedSSOCredentialsEncoder : ISSOCredentialsEncoder
314+ {
315+ #region Implementation of ISSOCredentialsEncoder
316+
317+ /// <summary>
318+ /// Encodes oauth credentials so that they can be stored in a keyring.
319+ /// </summary>
320+ /// <param name="token">The oauth token.</param>
321+ /// <param name="tokenSecret">The oauth secret.</param>
322+ /// <param name="consumerKey">The oauth consumer key.</param>
323+ /// <param name="consumerSecret">The oauth consumer secret.</param>
324+ /// <returns>a stirng that represents the oauth token.</returns>
325+ public string Encode(string token, string tokenSecret, string consumerKey, string consumerSecret)
326+ {
327+ return string.Format("{0}:{1}:{2}:{3}", token, tokenSecret, consumerKey, consumerSecret);
328+ }
329+
330+ /// <summary>
331+ /// Decodes the oauth credentials from a single string.
332+ /// </summary>
333+ /// <param name="secret">The secret that was stored in the keyring.</param>
334+ /// <param name="token">Out var where the ouath token will be returned.</param>
335+ /// <param name="tokenSecret">Out var where the oauth token secret will be returned.</param>
336+ /// <param name="consumerKey">Out var where the oauth consumer key will be returned.</param>
337+ /// <param name="consumerSecret">Out var where the oauth consumer secret will be returned.</param>
338+ public void Decode(string secret, out string token, out string tokenSecret, out string consumerKey, out string consumerSecret)
339+ {
340+ var data = secret.Split(":".ToCharArray(),4);
341+ token = data[0];
342+ tokenSecret = data[1];
343+ consumerKey = data[2];
344+ consumerSecret = data[3];
345+ }
346+
347+ #endregion
348+ }
349+}
350
351=== modified file 'src/Canonical.Ubuntu.SSO/DPAPIDataProtector.cs'
352--- src/Canonical.Ubuntu.SSO/DPAPIDataProtector.cs 2010-10-05 09:58:34 +0000
353+++ src/Canonical.Ubuntu.SSO/DPAPIDataProtector.cs 2010-10-05 09:58:35 +0000
354@@ -17,7 +17,6 @@
355 *
356 * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
357 */
358-
359 using System.Security.Cryptography;
360 using System.Text;
361 using log4net;
362
363=== added file 'src/Canonical.Ubuntu.SSO/IOAuth.cs'
364--- src/Canonical.Ubuntu.SSO/IOAuth.cs 1970-01-01 00:00:00 +0000
365+++ src/Canonical.Ubuntu.SSO/IOAuth.cs 2010-10-05 09:58:35 +0000
366@@ -0,0 +1,122 @@
367+/* Copyright 2010 Canonical Ltd.
368+ *
369+ * This file is part of UbuntuOne on Windows.
370+ *
371+ * UbuntuOne on Windows is free software: you can redistribute it and/or modify
372+ * it under the terms of the GNU Lesser General Public License version
373+ * as published by the Free Software Foundation.
374+ *
375+ * Ubuntu One on Windows is distributed in the hope that it will be useful,
376+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
377+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
378+ * GNU Lesser General Public License for more details.
379+ *
380+ * You should have received a copy of the GNU Lesser General Public License
381+ * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
382+ *
383+ * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
384+ */
385+using System;
386+using System.Collections.Generic;
387+using System.Security.Cryptography;
388+
389+namespace Canonical.Ubuntu.SSO
390+{
391+ public interface IOAuth
392+ {
393+ /// <summary>
394+ /// Generate the signature base that is used to produce the signature
395+ /// </summary>
396+ /// <param name="url">The full url that needs to be signed including its non OAuth url parameters</param>
397+ /// <param name="consumerKey">The consumer key</param>
398+ /// <param name="token">The token, if available. If not available pass null or an empty string</param>
399+ /// <param name="tokenSecret">The token secret, if available. If not available pass null or an empty string</param>
400+ /// <param name="httpMethod">The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)</param>
401+ /// <param name="nonce"></param>
402+ /// <param name="signatureType">The signature type. To use the default values use <see cref="OAuth.SignatureTypes">OAuth.SignatureTypes</see>.</param>
403+ /// <param name="timeStamp"></param>
404+ /// <param name="normalizedUrl"></param>
405+ /// <param name="normalizedRequestParameters"></param>
406+ /// <returns>The signature base</returns>
407+ string GenerateSignatureBase(Uri url, string consumerKey, string token, string tokenSecret,
408+ string httpMethod, string timeStamp, string nonce, string signatureType, out string normalizedUrl,
409+ out string normalizedRequestParameters);
410+
411+ /// <summary>
412+ /// Generate the signature value based on the given signature base and hash algorithm
413+ /// </summary>
414+ /// <param name="signatureBase">The signature based as produced by the GenerateSignatureBase method or by any other means</param>
415+ /// <param name="hash">The hash algorithm used to perform the hashing. If the hashing algorithm requires initialization or a key it should be set prior to calling this method</param>
416+ /// <returns>A base64 string of the hash value</returns>
417+ string GenerateSignatureUsingHash(string signatureBase, HashAlgorithm hash);
418+
419+ /// <summary>
420+ /// Generates a signature using the HMAC-SHA1 algorithm
421+ /// </summary>
422+ /// <param name="url">The full url that needs to be signed including its non OAuth url parameters</param>
423+ /// <param name="consumerKey">The consumer key</param>
424+ /// <param name="consumerSecret">The consumer seceret</param>
425+ /// <param name="token">The token, if available. If not available pass null or an empty string</param>
426+ /// <param name="tokenSecret">The token secret, if available. If not available pass null or an empty string</param>
427+ /// <param name="httpMethod">The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)</param>
428+ /// <param name="timeStamp"></param>
429+ /// <param name="nonce"></param>
430+ /// <param name="normalizedUrl"></param>
431+ /// <param name="normalizedRequestParameters"></param>
432+ /// <returns>A base64 string of the hash value</returns>
433+ string GenerateSignature(Uri url, string consumerKey, string consumerSecret, string token,
434+ string tokenSecret, string httpMethod, string timeStamp, string nonce, out string normalizedUrl,
435+ out string normalizedRequestParameters);
436+
437+ /// <summary>
438+ /// Generates a signature using the specified signatureType
439+ /// </summary>
440+ /// <param name="url">The full url that needs to be signed including its non OAuth url parameters</param>
441+ /// <param name="consumerKey">The consumer key</param>
442+ /// <param name="consumerSecret">The consumer seceret</param>
443+ /// <param name="token">The token, if available. If not available pass null or an empty string</param>
444+ /// <param name="tokenSecret">The token secret, if available. If not available pass null or an empty string</param>
445+ /// <param name="httpMethod">The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)</param>
446+ /// <param name="nonce"></param>
447+ /// <param name="signatureType">The type of signature to use</param>
448+ /// <param name="timeStamp"></param>
449+ /// <param name="normalizedUrl"></param>
450+ /// <param name="normalizedRequestParameters"></param>
451+ /// <returns>A base64 string of the hash value</returns>
452+ string GenerateSignature(Uri url, string consumerKey, string consumerSecret, string token,
453+ string tokenSecret, string httpMethod, string timeStamp, string nonce,
454+ OAuth.SignatureTypes signatureType, out string normalizedUrl, out string normalizedRequestParameters);
455+
456+ /// <summary>
457+ /// Returns a key value pair that contains a hedaer that can be used to authenticate a web requet.
458+ /// </summary>
459+ /// <param name="url">The uri with the web resource.</param>
460+ /// <param name="realm">The real that was used for the oauth.</param>
461+ /// <param name="consumerKey">The oauth consumer key.</param>
462+ /// <param name="consumerSecret">The oauth consumer secret.</param>
463+ /// <param name="token">The oauth token.</param>
464+ /// <param name="tokenSecret">The aoauth token secret.</param>
465+ /// <param name="httpMethod">The http method used for the request.</param>
466+ /// <param name="timeStamp">A time stamp.</param>
467+ /// <param name="nonce">A once</param>
468+ /// <param name="signatureType">Teht ype of signature that will be used.</param>
469+ /// <param name="normUrl"></param>
470+ /// <param name="normParams"></param>
471+ /// <returns>A key value pair where the key is the name of the header and the value is the data of the header.</returns>
472+ KeyValuePair<string, string> GenerateHeaderWithSignature(Uri url, string realm, string consumerKey,
473+ string consumerSecret, string token, string tokenSecret, string httpMethod, string timeStamp,
474+ string nonce, OAuth.SignatureTypes signatureType, out string normUrl, out string normParams);
475+
476+ /// <summary>
477+ /// Generate the timestamp for the signature
478+ /// </summary>
479+ /// <returns></returns>
480+ string GenerateTimeStamp();
481+
482+ /// <summary>
483+ /// Generate a nonce
484+ /// </summary>
485+ /// <returns></returns>
486+ string GenerateNonce();
487+ }
488+}
489\ No newline at end of file
490
491=== added file 'src/Canonical.Ubuntu.SSO/ISSOCredentialsEncoder.cs'
492--- src/Canonical.Ubuntu.SSO/ISSOCredentialsEncoder.cs 1970-01-01 00:00:00 +0000
493+++ src/Canonical.Ubuntu.SSO/ISSOCredentialsEncoder.cs 2010-10-05 09:58:35 +0000
494@@ -0,0 +1,46 @@
495+/* Copyright 2010 Canonical Ltd.
496+ *
497+ * This file is part of UbuntuOne on Windows.
498+ *
499+ * UbuntuOne on Windows is free software: you can redistribute it and/or modify
500+ * it under the terms of the GNU Lesser General Public License version
501+ * as published by the Free Software Foundation.
502+ *
503+ * Ubuntu One on Windows is distributed in the hope that it will be useful,
504+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
505+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
506+ * GNU Lesser General Public License for more details.
507+ *
508+ * You should have received a copy of the GNU Lesser General Public License
509+ * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
510+ *
511+ * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
512+ */
513+namespace Canonical.Ubuntu.SSO
514+{
515+ /// <summary>
516+ /// Interface to be implemented by those object that know how to encode a oauth token so that it is saved as a single string.
517+ /// </summary>
518+ public interface ISSOCredentialsEncoder
519+ {
520+ /// <summary>
521+ /// When implemented will encode oauth credentials so that they can be stored in a keyring.
522+ /// </summary>
523+ /// <param name="token">The oauth token.</param>
524+ /// <param name="tokenSecret">The oauth secret.</param>
525+ /// <param name="consumerKey">The oauth consumer key.</param>
526+ /// <param name="consumerSecret">The oauth consumer secret.</param>
527+ /// <returns>a stirng that represents the oauth token.</returns>
528+ string Encode(string token, string tokenSecret, string consumerKey, string consumerSecret);
529+
530+ /// <summary>
531+ /// When implemented decodes the oauth credentials from a single string.
532+ /// </summary>
533+ /// <param name="secret">The secret that was stored in the keyring.</param>
534+ /// <param name="token">Out var where the ouath token will be returned.</param>
535+ /// <param name="tokenSecret">Out var where the oauth token secret will be returned.</param>
536+ /// <param name="consumerKey">Out var where the oauth consumer key will be returned.</param>
537+ /// <param name="consumerSecret">Out var where the oauth consumer secret will be returned.</param>
538+ void Decode(string secret, out string token, out string tokenSecret, out string consumerKey, out string consumerSecret);
539+ }
540+}
541
542=== added file 'src/Canonical.Ubuntu.SSO/JsonSSOCredentialsEncoder.cs'
543--- src/Canonical.Ubuntu.SSO/JsonSSOCredentialsEncoder.cs 1970-01-01 00:00:00 +0000
544+++ src/Canonical.Ubuntu.SSO/JsonSSOCredentialsEncoder.cs 2010-10-05 09:58:35 +0000
545@@ -0,0 +1,82 @@
546+/* Copyright 2010 Canonical Ltd.
547+ *
548+ * This file is part of UbuntuOne on Windows.
549+ *
550+ * UbuntuOne on Windows is free software: you can redistribute it and/or modify
551+ * it under the terms of the GNU Lesser General Public License version
552+ * as published by the Free Software Foundation.
553+ *
554+ * Ubuntu One on Windows is distributed in the hope that it will be useful,
555+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
556+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
557+ * GNU Lesser General Public License for more details.
558+ *
559+ * You should have received a copy of the GNU Lesser General Public License
560+ * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
561+ *
562+ * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
563+ */
564+using System;
565+using Newtonsoft.Json.Linq;
566+
567+namespace Canonical.Ubuntu.SSO
568+{
569+ public class JsonSSOCredentialsEncoder : ISSOCredentialsEncoder
570+ {
571+ #region Implementation of ISSOCredentialsEncoder
572+
573+ /// <summary>
574+ /// When implemented will encode oauth credentials so that they can be stored in a keyring.
575+ /// </summary>
576+ /// <param name="token">The oauth token.</param>
577+ /// <param name="tokenSecret">The oauth secret.</param>
578+ /// <param name="consumerKey">The oauth consumer key.</param>
579+ /// <param name="consumerSecret">The oauth consumer secret.</param>
580+ /// <returns>a stirng that represents the oauth token.</returns>
581+ public string Encode(string token, string tokenSecret, string consumerKey, string consumerSecret)
582+ {
583+ var jobject = new JObject();
584+ jobject["consumer_key"] = "";
585+ jobject["consumer_secret"] = "";
586+ jobject["token"] = "";
587+ jobject["token_secret"] = "";
588+ return jobject.ToString();
589+ }
590+
591+ /// <summary>
592+ /// When implemented decodes the oauth credentials from a single string.
593+ /// </summary>
594+ /// <param name="secret">The secret that was stored in the keyring.</param>
595+ /// <param name="token">Out var where the ouath token will be returned.</param>
596+ /// <param name="tokenSecret">Out var where the oauth token secret will be returned.</param>
597+ /// <param name="consumerKey">Out var where the oauth consumer key will be returned.</param>
598+ /// <param name="consumerSecret">Out var where the oauth consumer secret will be returned.</param>
599+ public void Decode(string secret, out string token, out string tokenSecret, out string consumerKey, out string consumerSecret)
600+ {
601+ var credentials = JObject.Parse(secret);
602+ try
603+ {
604+ consumerKey = (string)credentials["consumer_key"];
605+ consumerSecret = (string)credentials["consumer_secret"];
606+ token = (string)credentials["token"];
607+ tokenSecret = (string)credentials["token_secret"];
608+
609+ }
610+ catch (InvalidCastException e)
611+ {
612+ // could happen when the json is not formatted as we expected.
613+ throw new SSOLoginException("Error when retrieving credentials.", e);
614+ }
615+ if (string.IsNullOrEmpty(consumerKey)
616+ || string.IsNullOrEmpty(consumerSecret)
617+ || string.IsNullOrEmpty(token)
618+ || string.IsNullOrEmpty(tokenSecret))
619+ {
620+ // none of them can be null or empty.
621+ throw new SSOException("Credentials could not be parsed.");
622+ }
623+ }
624+
625+ #endregion
626+ }
627+}
628
629=== added file 'src/Canonical.Ubuntu.SSO/OAuth.cs'
630--- src/Canonical.Ubuntu.SSO/OAuth.cs 1970-01-01 00:00:00 +0000
631+++ src/Canonical.Ubuntu.SSO/OAuth.cs 2010-10-05 09:58:35 +0000
632@@ -0,0 +1,391 @@
633+using System;
634+using System.Security.Cryptography;
635+using System.Collections.Generic;
636+using System.Text;
637+using System.Web;
638+
639+namespace Canonical.Ubuntu.SSO
640+{
641+ public class OAuth : IOAuth
642+ {
643+
644+ /// <summary>
645+ /// Provides a predefined set of algorithms that are supported officially by the protocol
646+ /// </summary>
647+ public enum SignatureTypes
648+ {
649+ HMACSHA1,
650+ PLAINTEXT,
651+ RSASHA1
652+ }
653+
654+ /// <summary>
655+ /// Provides an internal structure to sort the query parameter
656+ /// </summary>
657+ protected class QueryParameter
658+ {
659+ private readonly string _name = null;
660+ private readonly string _value = null;
661+
662+ public QueryParameter(string name, string value)
663+ {
664+ _name = name;
665+ _value = value;
666+ }
667+
668+ public string Name
669+ {
670+ get { return _name; }
671+ }
672+
673+ public string Value
674+ {
675+ get { return _value; }
676+ }
677+ }
678+
679+ /// <summary>
680+ /// Comparer class used to perform the sorting of the query parameters
681+ /// </summary>
682+ protected class QueryParameterComparer : IComparer<QueryParameter>
683+ {
684+
685+ #region IComparer<QueryParameter> Members
686+
687+ public int Compare(QueryParameter x, QueryParameter y)
688+ {
689+ return x.Name == y.Name ? string.Compare(x.Value, y.Value)
690+ : string.Compare(x.Name, y.Name);
691+ }
692+
693+ #endregion
694+ }
695+
696+ protected const string OAuthVersion = "1.0";
697+ protected const string OAuthParameterPrefix = "oauth_";
698+
699+ //
700+ // List of know and used oauth parameters' names
701+ //
702+ protected const string OAuthConsumerKeyKey = "oauth_consumer_key";
703+ protected const string OAuthCallbackKey = "oauth_callback";
704+ protected const string OAuthVersionKey = "oauth_version";
705+ protected const string OAuthSignatureMethodKey = "oauth_signature_method";
706+ protected const string OAuthSignatureKey = "oauth_signature";
707+ protected const string OAuthTimestampKey = "oauth_timestamp";
708+ protected const string OAuthNonceKey = "oauth_nonce";
709+ protected const string OAuthTokenKey = "oauth_token";
710+ protected const string OAuthTokenSecretKey = "oauth_token_secret";
711+
712+ protected const string HMACSHA1SignatureType = "HMAC-SHA1";
713+ protected const string PlainTextSignatureType = "PLAINTEXT";
714+ protected const string RSASHA1SignatureType = "RSA-SHA1";
715+
716+ protected Random Random = new Random();
717+
718+ protected string UnreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
719+
720+ /// <summary>
721+ /// Helper function to compute a hash value
722+ /// </summary>
723+ /// <param name="hashAlgorithm">The hashing algoirhtm used. If that algorithm needs some initialization, like HMAC and its derivatives, they should be initialized prior to passing it to this function</param>
724+ /// <param name="data">The data to hash</param>
725+ /// <returns>a Base64 string of the hash value</returns>
726+ private static string ComputeHash(HashAlgorithm hashAlgorithm, string data)
727+ {
728+ if (hashAlgorithm == null)
729+ {
730+ throw new ArgumentNullException("hashAlgorithm");
731+ }
732+
733+ if (string.IsNullOrEmpty(data))
734+ {
735+ throw new ArgumentNullException("data");
736+ }
737+
738+ var dataBuffer = Encoding.ASCII.GetBytes(data);
739+ var hashBytes = hashAlgorithm.ComputeHash(dataBuffer);
740+
741+ return Convert.ToBase64String(hashBytes);
742+ }
743+
744+ /// <summary>
745+ /// Internal function to cut out all non oauth query string parameters (all parameters not begining with "oauth_")
746+ /// </summary>
747+ /// <param name="parameters">The query string part of the Url</param>
748+ /// <returns>A list of QueryParameter each containing the parameter name and value</returns>
749+ private static List<QueryParameter> GetQueryParameters(string parameters)
750+ {
751+ if (parameters.StartsWith("?"))
752+ {
753+ parameters = parameters.Remove(0, 1);
754+ }
755+
756+ var result = new List<QueryParameter>();
757+
758+ if (!string.IsNullOrEmpty(parameters))
759+ {
760+ string[] p = parameters.Split('&');
761+ foreach (string s in p)
762+ {
763+ if (!string.IsNullOrEmpty(s) && !s.StartsWith(OAuthParameterPrefix))
764+ {
765+ if (s.IndexOf('=') > -1)
766+ {
767+ string[] temp = s.Split('=');
768+ result.Add(new QueryParameter(temp[0], temp[1]));
769+ }
770+ else
771+ {
772+ result.Add(new QueryParameter(s, string.Empty));
773+ }
774+ }
775+ }
776+ }
777+
778+ return result;
779+ }
780+
781+ /// <summary>
782+ /// This is a different Url Encode implementation since the default .NET one outputs the percent encoding in lower case.
783+ /// While this is not a problem with the percent encoding spec, it is used in upper case throughout OAuth
784+ /// </summary>
785+ /// <param name="value">The value to Url encode</param>
786+ /// <returns>Returns a Url encoded string</returns>
787+ protected string UrlEncode(string value)
788+ {
789+ var result = new StringBuilder();
790+
791+ foreach (char symbol in value)
792+ {
793+ if (UnreservedChars.IndexOf(symbol) != -1)
794+ {
795+ result.Append(symbol);
796+ }
797+ else
798+ {
799+ result.Append('%' + String.Format("{0:X2}", (int)symbol));
800+ }
801+ }
802+
803+ return result.ToString();
804+ }
805+
806+ /// <summary>
807+ /// Normalizes the request parameters according to the spec
808+ /// </summary>
809+ /// <param name="parameters">The list of parameters already sorted</param>
810+ /// <returns>a string representing the normalized parameters</returns>
811+ protected string NormalizeRequestParameters(IList<QueryParameter> parameters)
812+ {
813+ var sb = new StringBuilder();
814+ QueryParameter p;
815+ for (var i = 0; i < parameters.Count; i++)
816+ {
817+ p = parameters[i];
818+ sb.AppendFormat("{0}={1}", p.Name, p.Value);
819+
820+ if (i < parameters.Count - 1)
821+ {
822+ sb.Append("&");
823+ }
824+ }
825+
826+ return sb.ToString();
827+ }
828+
829+ /// <summary>
830+ /// Generate the signature base that is used to produce the signature
831+ /// </summary>
832+ /// <param name="url">The full url that needs to be signed including its non OAuth url parameters</param>
833+ /// <param name="consumerKey">The consumer key</param>
834+ /// <param name="token">The token, if available. If not available pass null or an empty string</param>
835+ /// <param name="tokenSecret">The token secret, if available. If not available pass null or an empty string</param>
836+ /// <param name="httpMethod">The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)</param>
837+ /// <param name="nonce"></param>
838+ /// <param name="signatureType">The signature type. To use the default values use <see cref="OAuth.SignatureTypes">OAuth.SignatureTypes</see>.</param>
839+ /// <param name="timeStamp"></param>
840+ /// <param name="normalizedUrl"></param>
841+ /// <param name="normalizedRequestParameters"></param>
842+ /// <returns>The signature base</returns>
843+ public string GenerateSignatureBase(Uri url, string consumerKey, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, string signatureType, out string normalizedUrl, out string normalizedRequestParameters)
844+ {
845+ if (token == null)
846+ {
847+ token = string.Empty;
848+ }
849+
850+ if (tokenSecret == null)
851+ {
852+ tokenSecret = string.Empty;
853+ }
854+
855+ if (string.IsNullOrEmpty(consumerKey))
856+ {
857+ throw new ArgumentNullException("consumerKey");
858+ }
859+
860+ if (string.IsNullOrEmpty(httpMethod))
861+ {
862+ throw new ArgumentNullException("httpMethod");
863+ }
864+
865+ if (string.IsNullOrEmpty(signatureType))
866+ {
867+ throw new ArgumentNullException("signatureType");
868+ }
869+
870+ List<QueryParameter> parameters = GetQueryParameters(url.Query);
871+ parameters.Add(new QueryParameter(OAuthVersionKey, OAuthVersion));
872+ parameters.Add(new QueryParameter(OAuthNonceKey, nonce));
873+ parameters.Add(new QueryParameter(OAuthTimestampKey, timeStamp));
874+ parameters.Add(new QueryParameter(OAuthSignatureMethodKey, signatureType));
875+ parameters.Add(new QueryParameter(OAuthConsumerKeyKey, consumerKey));
876+
877+ if (!string.IsNullOrEmpty(token))
878+ {
879+ parameters.Add(new QueryParameter(OAuthTokenKey, token));
880+ }
881+
882+ parameters.Sort(new QueryParameterComparer());
883+
884+ normalizedUrl = string.Format("{0}://{1}", url.Scheme, url.Host);
885+ if (!((url.Scheme == "http" && url.Port == 80) || (url.Scheme == "https" && url.Port == 443)))
886+ {
887+ normalizedUrl += ":" + url.Port;
888+ }
889+ normalizedUrl += url.AbsolutePath;
890+ normalizedRequestParameters = NormalizeRequestParameters(parameters);
891+
892+ var signatureBase = new StringBuilder();
893+ signatureBase.AppendFormat("{0}&", httpMethod.ToUpper());
894+ signatureBase.AppendFormat("{0}&", UrlEncode(normalizedUrl));
895+ signatureBase.AppendFormat("{0}", UrlEncode(normalizedRequestParameters));
896+
897+ return signatureBase.ToString();
898+ }
899+
900+ /// <summary>
901+ /// Generate the signature value based on the given signature base and hash algorithm
902+ /// </summary>
903+ /// <param name="signatureBase">The signature based as produced by the GenerateSignatureBase method or by any other means</param>
904+ /// <param name="hash">The hash algorithm used to perform the hashing. If the hashing algorithm requires initialization or a key it should be set prior to calling this method</param>
905+ /// <returns>A base64 string of the hash value</returns>
906+ public string GenerateSignatureUsingHash(string signatureBase, HashAlgorithm hash)
907+ {
908+ return ComputeHash(hash, signatureBase);
909+ }
910+
911+ /// <summary>
912+ /// Generates a signature using the HMAC-SHA1 algorithm
913+ /// </summary>
914+ /// <param name="url">The full url that needs to be signed including its non OAuth url parameters</param>
915+ /// <param name="consumerKey">The consumer key</param>
916+ /// <param name="consumerSecret">The consumer seceret</param>
917+ /// <param name="token">The token, if available. If not available pass null or an empty string</param>
918+ /// <param name="tokenSecret">The token secret, if available. If not available pass null or an empty string</param>
919+ /// <param name="httpMethod">The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)</param>
920+ /// <param name="timeStamp"></param>
921+ /// <param name="nonce"></param>
922+ /// <param name="normalizedUrl"></param>
923+ /// <param name="normalizedRequestParameters"></param>
924+ /// <returns>A base64 string of the hash value</returns>
925+ public string GenerateSignature(Uri url, string consumerKey, string consumerSecret, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, out string normalizedUrl, out string normalizedRequestParameters)
926+ {
927+ return GenerateSignature(url, consumerKey, consumerSecret, token, tokenSecret, httpMethod, timeStamp, nonce, SignatureTypes.HMACSHA1, out normalizedUrl, out normalizedRequestParameters);
928+ }
929+
930+ /// <summary>
931+ /// Generates a signature using the specified signatureType
932+ /// </summary>
933+ /// <param name="url">The full url that needs to be signed including its non OAuth url parameters</param>
934+ /// <param name="consumerKey">The consumer key</param>
935+ /// <param name="consumerSecret">The consumer seceret</param>
936+ /// <param name="token">The token, if available. If not available pass null or an empty string</param>
937+ /// <param name="tokenSecret">The token secret, if available. If not available pass null or an empty string</param>
938+ /// <param name="httpMethod">The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)</param>
939+ /// <param name="nonce"></param>
940+ /// <param name="signatureType">The type of signature to use</param>
941+ /// <param name="timeStamp"></param>
942+ /// <param name="normalizedUrl"></param>
943+ /// <param name="normalizedRequestParameters"></param>
944+ /// <returns>A base64 string of the hash value</returns>
945+ public string GenerateSignature(Uri url, string consumerKey, string consumerSecret, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, SignatureTypes signatureType, out string normalizedUrl, out string normalizedRequestParameters)
946+ {
947+ normalizedUrl = null;
948+ normalizedRequestParameters = null;
949+
950+ switch (signatureType)
951+ {
952+ case SignatureTypes.PLAINTEXT:
953+ return HttpUtility.UrlEncode(string.Format("{0}&{1}", consumerSecret, tokenSecret));
954+ case SignatureTypes.HMACSHA1:
955+ var signatureBase = GenerateSignatureBase(url, consumerKey, token, tokenSecret, httpMethod, timeStamp, nonce, HMACSHA1SignatureType, out normalizedUrl, out normalizedRequestParameters);
956+
957+ var hmacsha1 = new HMACSHA1();
958+ hmacsha1.Key = Encoding.ASCII.GetBytes(string.Format("{0}&{1}", UrlEncode(consumerSecret), string.IsNullOrEmpty(tokenSecret) ? "" : UrlEncode(tokenSecret)));
959+
960+ return GenerateSignatureUsingHash(signatureBase, hmacsha1);
961+ case SignatureTypes.RSASHA1:
962+ throw new NotImplementedException();
963+ default:
964+ throw new ArgumentException("Unknown signature type", "signatureType");
965+ }
966+ }
967+
968+ /// <summary>
969+ /// Returns a key value pair that contains a hedaer that can be used to authenticate a web requet.
970+ /// </summary>
971+ /// <param name="url">The uri with the web resource.</param>
972+ /// <param name="realm">The real that was used for the oauth.</param>
973+ /// <param name="consumerKey">The oauth consumer key.</param>
974+ /// <param name="consumerSecret">The oauth consumer secret.</param>
975+ /// <param name="token">The oauth token.</param>
976+ /// <param name="tokenSecret">The aoauth token secret.</param>
977+ /// <param name="httpMethod">The http method used for the request.</param>
978+ /// <param name="timeStamp">A time stamp.</param>
979+ /// <param name="nonce">A once</param>
980+ /// <param name="signatureType">Teht ype of signature that will be used.</param>
981+ /// <returns>A key value pair where the key is the name of the header and the value is the data of the header.</returns>
982+ public KeyValuePair<string, string> GenerateHeaderWithSignature(Uri url, string realm, string consumerKey,
983+ string consumerSecret, string token, string tokenSecret, string httpMethod, string timeStamp,
984+ string nonce, SignatureTypes signatureType, out string normUrl, out string normParams)
985+ {
986+ var signature = GenerateSignature(url,
987+ consumerKey, consumerSecret, token, tokenSecret,
988+ httpMethod, timeStamp, nonce, SignatureTypes.HMACSHA1,
989+ out normUrl, out normParams);
990+
991+ // Construct the OAuth header
992+ var headerData = normParams + "&" + HttpUtility.UrlEncode("oauth_signature") + "=" + HttpUtility.UrlEncode(signature);
993+ headerData = headerData.Replace("&", @""",");
994+ headerData = headerData.Replace("=", @"=""");
995+ headerData += @"""";
996+ headerData = ((string.IsNullOrEmpty(realm)) ? "OAuth realm=\"\"," :
997+ string.Format("OAuth realm=\"{0}\",", realm)) + headerData;
998+ return new KeyValuePair<string, string>("Authorization", headerData);
999+ }
1000+
1001+ /// <summary>
1002+ /// Generate the timestamp for the signature
1003+ /// </summary>
1004+ /// <returns></returns>
1005+ public virtual string GenerateTimeStamp()
1006+ {
1007+ // Default implementation of UNIX time of the current UTC time
1008+ TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
1009+ return Convert.ToInt64(ts.TotalSeconds).ToString();
1010+ }
1011+
1012+ /// <summary>
1013+ /// Generate a nonce
1014+ /// </summary>
1015+ /// <returns></returns>
1016+ public virtual string GenerateNonce()
1017+ {
1018+ // Just a simple implementation of a random number between 123400 and 9999999
1019+ return Random.Next(123400, 9999999).ToString();
1020+ }
1021+
1022+ }
1023+}
1024\ No newline at end of file
1025
1026=== removed file 'src/Canonical.Ubuntu.SSO/OAuthBase.cs'
1027--- src/Canonical.Ubuntu.SSO/OAuthBase.cs 2010-10-05 09:58:34 +0000
1028+++ src/Canonical.Ubuntu.SSO/OAuthBase.cs 1970-01-01 00:00:00 +0000
1029@@ -1,358 +0,0 @@
1030-using System;
1031-using System.Security.Cryptography;
1032-using System.Collections.Generic;
1033-using System.Text;
1034-using System.Web;
1035-
1036-namespace OAuth
1037-{
1038- public class OAuthBase
1039- {
1040-
1041- /// <summary>
1042- /// Provides a predefined set of algorithms that are supported officially by the protocol
1043- /// </summary>
1044- public enum SignatureTypes
1045- {
1046- HMACSHA1,
1047- PLAINTEXT,
1048- RSASHA1
1049- }
1050-
1051- /// <summary>
1052- /// Provides an internal structure to sort the query parameter
1053- /// </summary>
1054- protected class QueryParameter
1055- {
1056- private readonly string _name = null;
1057- private readonly string _value = null;
1058-
1059- public QueryParameter(string name, string value)
1060- {
1061- _name = name;
1062- _value = value;
1063- }
1064-
1065- public string Name
1066- {
1067- get { return _name; }
1068- }
1069-
1070- public string Value
1071- {
1072- get { return _value; }
1073- }
1074- }
1075-
1076- /// <summary>
1077- /// Comparer class used to perform the sorting of the query parameters
1078- /// </summary>
1079- protected class QueryParameterComparer : IComparer<QueryParameter>
1080- {
1081-
1082- #region IComparer<QueryParameter> Members
1083-
1084- public int Compare(QueryParameter x, QueryParameter y)
1085- {
1086- return x.Name == y.Name ? string.Compare(x.Value, y.Value)
1087- : string.Compare(x.Name, y.Name);
1088- }
1089-
1090- #endregion
1091- }
1092-
1093- protected const string OAuthVersion = "1.0";
1094- protected const string OAuthParameterPrefix = "oauth_";
1095-
1096- //
1097- // List of know and used oauth parameters' names
1098- //
1099- protected const string OAuthConsumerKeyKey = "oauth_consumer_key";
1100- protected const string OAuthCallbackKey = "oauth_callback";
1101- protected const string OAuthVersionKey = "oauth_version";
1102- protected const string OAuthSignatureMethodKey = "oauth_signature_method";
1103- protected const string OAuthSignatureKey = "oauth_signature";
1104- protected const string OAuthTimestampKey = "oauth_timestamp";
1105- protected const string OAuthNonceKey = "oauth_nonce";
1106- protected const string OAuthTokenKey = "oauth_token";
1107- protected const string OAuthTokenSecretKey = "oauth_token_secret";
1108-
1109- protected const string HMACSHA1SignatureType = "HMAC-SHA1";
1110- protected const string PlainTextSignatureType = "PLAINTEXT";
1111- protected const string RSASHA1SignatureType = "RSA-SHA1";
1112-
1113- protected Random Random = new Random();
1114-
1115- protected string UnreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
1116-
1117- /// <summary>
1118- /// Helper function to compute a hash value
1119- /// </summary>
1120- /// <param name="hashAlgorithm">The hashing algoirhtm used. If that algorithm needs some initialization, like HMAC and its derivatives, they should be initialized prior to passing it to this function</param>
1121- /// <param name="data">The data to hash</param>
1122- /// <returns>a Base64 string of the hash value</returns>
1123- private static string ComputeHash(HashAlgorithm hashAlgorithm, string data)
1124- {
1125- if (hashAlgorithm == null)
1126- {
1127- throw new ArgumentNullException("hashAlgorithm");
1128- }
1129-
1130- if (string.IsNullOrEmpty(data))
1131- {
1132- throw new ArgumentNullException("data");
1133- }
1134-
1135- var dataBuffer = Encoding.ASCII.GetBytes(data);
1136- var hashBytes = hashAlgorithm.ComputeHash(dataBuffer);
1137-
1138- return Convert.ToBase64String(hashBytes);
1139- }
1140-
1141- /// <summary>
1142- /// Internal function to cut out all non oauth query string parameters (all parameters not begining with "oauth_")
1143- /// </summary>
1144- /// <param name="parameters">The query string part of the Url</param>
1145- /// <returns>A list of QueryParameter each containing the parameter name and value</returns>
1146- private static List<QueryParameter> GetQueryParameters(string parameters)
1147- {
1148- if (parameters.StartsWith("?"))
1149- {
1150- parameters = parameters.Remove(0, 1);
1151- }
1152-
1153- var result = new List<QueryParameter>();
1154-
1155- if (!string.IsNullOrEmpty(parameters))
1156- {
1157- string[] p = parameters.Split('&');
1158- foreach (string s in p)
1159- {
1160- if (!string.IsNullOrEmpty(s) && !s.StartsWith(OAuthParameterPrefix))
1161- {
1162- if (s.IndexOf('=') > -1)
1163- {
1164- string[] temp = s.Split('=');
1165- result.Add(new QueryParameter(temp[0], temp[1]));
1166- }
1167- else
1168- {
1169- result.Add(new QueryParameter(s, string.Empty));
1170- }
1171- }
1172- }
1173- }
1174-
1175- return result;
1176- }
1177-
1178- /// <summary>
1179- /// This is a different Url Encode implementation since the default .NET one outputs the percent encoding in lower case.
1180- /// While this is not a problem with the percent encoding spec, it is used in upper case throughout OAuth
1181- /// </summary>
1182- /// <param name="value">The value to Url encode</param>
1183- /// <returns>Returns a Url encoded string</returns>
1184- protected string UrlEncode(string value)
1185- {
1186- var result = new StringBuilder();
1187-
1188- foreach (char symbol in value)
1189- {
1190- if (UnreservedChars.IndexOf(symbol) != -1)
1191- {
1192- result.Append(symbol);
1193- }
1194- else
1195- {
1196- result.Append('%' + String.Format("{0:X2}", (int)symbol));
1197- }
1198- }
1199-
1200- return result.ToString();
1201- }
1202-
1203- /// <summary>
1204- /// Normalizes the request parameters according to the spec
1205- /// </summary>
1206- /// <param name="parameters">The list of parameters already sorted</param>
1207- /// <returns>a string representing the normalized parameters</returns>
1208- protected string NormalizeRequestParameters(IList<QueryParameter> parameters)
1209- {
1210- var sb = new StringBuilder();
1211- QueryParameter p;
1212- for (var i = 0; i < parameters.Count; i++)
1213- {
1214- p = parameters[i];
1215- sb.AppendFormat("{0}={1}", p.Name, p.Value);
1216-
1217- if (i < parameters.Count - 1)
1218- {
1219- sb.Append("&");
1220- }
1221- }
1222-
1223- return sb.ToString();
1224- }
1225-
1226- /// <summary>
1227- /// Generate the signature base that is used to produce the signature
1228- /// </summary>
1229- /// <param name="url">The full url that needs to be signed including its non OAuth url parameters</param>
1230- /// <param name="consumerKey">The consumer key</param>
1231- /// <param name="token">The token, if available. If not available pass null or an empty string</param>
1232- /// <param name="tokenSecret">The token secret, if available. If not available pass null or an empty string</param>
1233- /// <param name="httpMethod">The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)</param>
1234- /// <param name="nonce"></param>
1235- /// <param name="signatureType">The signature type. To use the default values use <see cref="OAuthBase.SignatureTypes">OAuthBase.SignatureTypes</see>.</param>
1236- /// <param name="timeStamp"></param>
1237- /// <param name="normalizedUrl"></param>
1238- /// <param name="normalizedRequestParameters"></param>
1239- /// <returns>The signature base</returns>
1240- public string GenerateSignatureBase(Uri url, string consumerKey, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, string signatureType, out string normalizedUrl, out string normalizedRequestParameters)
1241- {
1242- if (token == null)
1243- {
1244- token = string.Empty;
1245- }
1246-
1247- if (tokenSecret == null)
1248- {
1249- tokenSecret = string.Empty;
1250- }
1251-
1252- if (string.IsNullOrEmpty(consumerKey))
1253- {
1254- throw new ArgumentNullException("consumerKey");
1255- }
1256-
1257- if (string.IsNullOrEmpty(httpMethod))
1258- {
1259- throw new ArgumentNullException("httpMethod");
1260- }
1261-
1262- if (string.IsNullOrEmpty(signatureType))
1263- {
1264- throw new ArgumentNullException("signatureType");
1265- }
1266-
1267- List<QueryParameter> parameters = GetQueryParameters(url.Query);
1268- parameters.Add(new QueryParameter(OAuthVersionKey, OAuthVersion));
1269- parameters.Add(new QueryParameter(OAuthNonceKey, nonce));
1270- parameters.Add(new QueryParameter(OAuthTimestampKey, timeStamp));
1271- parameters.Add(new QueryParameter(OAuthSignatureMethodKey, signatureType));
1272- parameters.Add(new QueryParameter(OAuthConsumerKeyKey, consumerKey));
1273-
1274- if (!string.IsNullOrEmpty(token))
1275- {
1276- parameters.Add(new QueryParameter(OAuthTokenKey, token));
1277- }
1278-
1279- parameters.Sort(new QueryParameterComparer());
1280-
1281- normalizedUrl = string.Format("{0}://{1}", url.Scheme, url.Host);
1282- if (!((url.Scheme == "http" && url.Port == 80) || (url.Scheme == "https" && url.Port == 443)))
1283- {
1284- normalizedUrl += ":" + url.Port;
1285- }
1286- normalizedUrl += url.AbsolutePath;
1287- normalizedRequestParameters = NormalizeRequestParameters(parameters);
1288-
1289- var signatureBase = new StringBuilder();
1290- signatureBase.AppendFormat("{0}&", httpMethod.ToUpper());
1291- signatureBase.AppendFormat("{0}&", UrlEncode(normalizedUrl));
1292- signatureBase.AppendFormat("{0}", UrlEncode(normalizedRequestParameters));
1293-
1294- return signatureBase.ToString();
1295- }
1296-
1297- /// <summary>
1298- /// Generate the signature value based on the given signature base and hash algorithm
1299- /// </summary>
1300- /// <param name="signatureBase">The signature based as produced by the GenerateSignatureBase method or by any other means</param>
1301- /// <param name="hash">The hash algorithm used to perform the hashing. If the hashing algorithm requires initialization or a key it should be set prior to calling this method</param>
1302- /// <returns>A base64 string of the hash value</returns>
1303- public string GenerateSignatureUsingHash(string signatureBase, HashAlgorithm hash)
1304- {
1305- return ComputeHash(hash, signatureBase);
1306- }
1307-
1308- /// <summary>
1309- /// Generates a signature using the HMAC-SHA1 algorithm
1310- /// </summary>
1311- /// <param name="url">The full url that needs to be signed including its non OAuth url parameters</param>
1312- /// <param name="consumerKey">The consumer key</param>
1313- /// <param name="consumerSecret">The consumer seceret</param>
1314- /// <param name="token">The token, if available. If not available pass null or an empty string</param>
1315- /// <param name="tokenSecret">The token secret, if available. If not available pass null or an empty string</param>
1316- /// <param name="httpMethod">The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)</param>
1317- /// <param name="timeStamp"></param>
1318- /// <param name="nonce"></param>
1319- /// <param name="normalizedUrl"></param>
1320- /// <param name="normalizedRequestParameters"></param>
1321- /// <returns>A base64 string of the hash value</returns>
1322- public string GenerateSignature(Uri url, string consumerKey, string consumerSecret, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, out string normalizedUrl, out string normalizedRequestParameters)
1323- {
1324- return GenerateSignature(url, consumerKey, consumerSecret, token, tokenSecret, httpMethod, timeStamp, nonce, SignatureTypes.HMACSHA1, out normalizedUrl, out normalizedRequestParameters);
1325- }
1326-
1327- /// <summary>
1328- /// Generates a signature using the specified signatureType
1329- /// </summary>
1330- /// <param name="url">The full url that needs to be signed including its non OAuth url parameters</param>
1331- /// <param name="consumerKey">The consumer key</param>
1332- /// <param name="consumerSecret">The consumer seceret</param>
1333- /// <param name="token">The token, if available. If not available pass null or an empty string</param>
1334- /// <param name="tokenSecret">The token secret, if available. If not available pass null or an empty string</param>
1335- /// <param name="httpMethod">The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)</param>
1336- /// <param name="nonce"></param>
1337- /// <param name="signatureType">The type of signature to use</param>
1338- /// <param name="timeStamp"></param>
1339- /// <param name="normalizedUrl"></param>
1340- /// <param name="normalizedRequestParameters"></param>
1341- /// <returns>A base64 string of the hash value</returns>
1342- public string GenerateSignature(Uri url, string consumerKey, string consumerSecret, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, SignatureTypes signatureType, out string normalizedUrl, out string normalizedRequestParameters)
1343- {
1344- normalizedUrl = null;
1345- normalizedRequestParameters = null;
1346-
1347- switch (signatureType)
1348- {
1349- case SignatureTypes.PLAINTEXT:
1350- return HttpUtility.UrlEncode(string.Format("{0}&{1}", consumerSecret, tokenSecret));
1351- case SignatureTypes.HMACSHA1:
1352- var signatureBase = GenerateSignatureBase(url, consumerKey, token, tokenSecret, httpMethod, timeStamp, nonce, HMACSHA1SignatureType, out normalizedUrl, out normalizedRequestParameters);
1353-
1354- var hmacsha1 = new HMACSHA1();
1355- hmacsha1.Key = Encoding.ASCII.GetBytes(string.Format("{0}&{1}", UrlEncode(consumerSecret), string.IsNullOrEmpty(tokenSecret) ? "" : UrlEncode(tokenSecret)));
1356-
1357- return GenerateSignatureUsingHash(signatureBase, hmacsha1);
1358- case SignatureTypes.RSASHA1:
1359- throw new NotImplementedException();
1360- default:
1361- throw new ArgumentException("Unknown signature type", "signatureType");
1362- }
1363- }
1364-
1365- /// <summary>
1366- /// Generate the timestamp for the signature
1367- /// </summary>
1368- /// <returns></returns>
1369- public virtual string GenerateTimeStamp()
1370- {
1371- // Default implementation of UNIX time of the current UTC time
1372- TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
1373- return Convert.ToInt64(ts.TotalSeconds).ToString();
1374- }
1375-
1376- /// <summary>
1377- /// Generate a nonce
1378- /// </summary>
1379- /// <returns></returns>
1380- public virtual string GenerateNonce()
1381- {
1382- // Just a simple implementation of a random number between 123400 and 9999999
1383- return Random.Next(123400, 9999999).ToString();
1384- }
1385-
1386- }
1387-}
1388\ No newline at end of file
1389
1390=== added file 'src/Canonical.Ubuntu.SSO/SSOException.cs'
1391--- src/Canonical.Ubuntu.SSO/SSOException.cs 1970-01-01 00:00:00 +0000
1392+++ src/Canonical.Ubuntu.SSO/SSOException.cs 2010-10-05 09:58:35 +0000
1393@@ -0,0 +1,57 @@
1394+/* Copyright 2010 Canonical Ltd.
1395+ *
1396+ * This file is part of UbuntuOne on Windows.
1397+ *
1398+ * UbuntuOne on Windows is free software: you can redistribute it and/or modify
1399+ * it under the terms of the GNU Lesser General Public License version
1400+ * as published by the Free Software Foundation.
1401+ *
1402+ * Ubuntu One on Windows is distributed in the hope that it will be useful,
1403+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1404+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1405+ * GNU Lesser General Public License for more details.
1406+ *
1407+ * You should have received a copy of the GNU Lesser General Public License
1408+ * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
1409+ *
1410+ * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
1411+ */
1412+using System;
1413+
1414+namespace Canonical.Ubuntu.SSO
1415+{
1416+ /// <summary>
1417+ /// Root exception class for all those SSO problems.
1418+ /// </summary>
1419+ public class SSOException : Exception
1420+ {
1421+ /// <summary>
1422+ /// Creates a new instance of the class with no message or inner exception.
1423+ /// </summary>
1424+ public SSOException()
1425+ {
1426+
1427+ }
1428+
1429+ /// <summary>
1430+ /// Creates a new instance of the class with the given message.
1431+ /// </summary>
1432+ /// <param name="message">The message to be carried by the exception.</param>
1433+ public SSOException(string message)
1434+ : base(message)
1435+ {
1436+
1437+ }
1438+
1439+ /// <summary>
1440+ /// Creates a new instance of the class with the given message and inner exception.
1441+ /// </summary>
1442+ /// <param name="message">The message to be carried by the exception.</param>
1443+ /// <param name="e">The inner exception.</param>
1444+ public SSOException(string message, Exception e)
1445+ : base(message, e)
1446+ {
1447+
1448+ }
1449+ }
1450+}
1451
1452=== added file 'src/Canonical.Ubuntu.SSO/SSOLoginException.cs'
1453--- src/Canonical.Ubuntu.SSO/SSOLoginException.cs 1970-01-01 00:00:00 +0000
1454+++ src/Canonical.Ubuntu.SSO/SSOLoginException.cs 2010-10-05 09:58:35 +0000
1455@@ -0,0 +1,57 @@
1456+/* Copyright 2010 Canonical Ltd.
1457+ *
1458+ * This file is part of UbuntuOne on Windows.
1459+ *
1460+ * UbuntuOne on Windows is free software: you can redistribute it and/or modify
1461+ * it under the terms of the GNU Lesser General Public License version
1462+ * as published by the Free Software Foundation.
1463+ *
1464+ * Ubuntu One on Windows is distributed in the hope that it will be useful,
1465+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1466+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1467+ * GNU Lesser General Public License for more details.
1468+ *
1469+ * You should have received a copy of the GNU Lesser General Public License
1470+ * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
1471+ *
1472+ * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
1473+ */
1474+using System;
1475+
1476+namespace Canonical.Ubuntu.SSO
1477+{
1478+ /// <summary>
1479+ /// Exception thrown when there are errors during a login.
1480+ /// </summary>
1481+ public class SSOLoginException : SSOException
1482+ {
1483+ /// <summary>
1484+ /// Creates a new instance of the class with no message or inner exception.
1485+ /// </summary>
1486+ public SSOLoginException()
1487+ {
1488+
1489+ }
1490+
1491+ /// <summary>
1492+ /// Creates a new instance of the class with the given message.
1493+ /// </summary>
1494+ /// <param name="message">The message to be carried by the exception.</param>
1495+ public SSOLoginException(string message)
1496+ : base(message)
1497+ {
1498+
1499+ }
1500+
1501+ /// <summary>
1502+ /// Creates a new instance of the class with the given message and inner exception.
1503+ /// </summary>
1504+ /// <param name="message">The message to be carried by the exception.</param>
1505+ /// <param name="e">The inner exception.</param>
1506+ public SSOLoginException(string message, Exception e)
1507+ : base(message, e)
1508+ {
1509+
1510+ }
1511+ }
1512+}
1513
1514=== modified file 'src/Canonical.Ubuntu.SSO/SSOLoginProcessor.cs'
1515--- src/Canonical.Ubuntu.SSO/SSOLoginProcessor.cs 2010-09-20 11:21:19 +0000
1516+++ src/Canonical.Ubuntu.SSO/SSOLoginProcessor.cs 2010-10-05 09:58:35 +0000
1517@@ -18,6 +18,10 @@
1518 * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
1519 */
1520 using System;
1521+using System.Net;
1522+using Canonical.Ubuntu.SSO.Service;
1523+using Canonical.UbuntuOne.Common.Net;
1524+using Newtonsoft.Json.Linq;
1525
1526 namespace Canonical.Ubuntu.SSO
1527 {
1528@@ -27,6 +31,126 @@
1529 /// </summary>
1530 public class SSOLoginProcessor : ISSOLoginProcessor
1531 {
1532+ private const string ApplicationTokenName = "Ubuntu One @ {0} (Windows)";
1533+ internal const string KeyringName = "Default";
1534+ internal const string ApplicationName = "UbuntuOne";
1535+
1536+ #region DI properties
1537+
1538+ /// <summary>
1539+ /// Gets and sets the Authentications rest service that is used to authenticate the user.
1540+ /// </summary>
1541+ public Authentications Authentications { get; set; }
1542+
1543+ /// <summary>
1544+ /// Gets and sets the keyring that will be used to store the secrets.
1545+ /// </summary>
1546+ public IKeyring Keyring { get; set; }
1547+
1548+ /// <summary>
1549+ /// Gets and sets the credential encoder that will be used to encode the oauth credentials
1550+ /// before they are saved in the keyring.
1551+ /// </summary>
1552+ public ISSOCredentialsEncoder SSOCredentialsEncoder { get; set; }
1553+
1554+ /// <summary>
1555+ /// Gets and sets the object that will take care of the oauth operations.
1556+ /// </summary>
1557+ public IOAuth OAuth { get; set; }
1558+
1559+ public IHttpWebRequestFactory HttpWebRequestFactory { get; set; }
1560+
1561+ #endregion
1562+
1563+ #region Helper methods}
1564+
1565+ /// <summary>
1566+ /// Creates an oauth request that can access a protected web resource.
1567+ /// </summary>
1568+ /// <param name="uri">The uri where the resource is found.</param>
1569+ /// <param name="httpMethod">The request berb to be used.</param>
1570+ /// <param name="consumerKey">Consumer key from oauth.</param>
1571+ /// <param name="consumerSecret">Consumer secret from oauth.</param>
1572+ /// <param name="token">Token from oauth.</param>
1573+ /// <param name="tokenSecret">Token secret from oauth.</param>
1574+ /// <returns>A webrequest that can be used to access the resource.</returns>
1575+ public IHttpWebRequest MakeRequest(string uri, string httpMethod, string consumerKey, string consumerSecret, string token, string tokenSecret)
1576+ {
1577+ // Form the full REST request url
1578+ var url = new Uri(uri);
1579+ string normUrl;
1580+ string normParams;
1581+
1582+ // get oauth header
1583+ var authHeader = OAuth.GenerateHeaderWithSignature(url, string.Empty, consumerKey, consumerSecret,
1584+ token, tokenSecret, httpMethod, OAuth.GenerateTimeStamp(), OAuth.GenerateNonce(), SSO.OAuth.SignatureTypes.HMACSHA1,
1585+ out normUrl, out normParams);
1586+
1587+ var request = HttpWebRequestFactory.Create(url);
1588+ request.Headers.Add(authHeader.Key, authHeader.Value);
1589+ return request;
1590+ }
1591+
1592+ /// <summary>
1593+ /// Pings the Ubuntu One server so that the SSO tokens are added to them and they know how to identify the user.
1594+ /// </summary>
1595+ /// <param name="email">The email used by the user to register to u1.</param>
1596+ /// <param name="consumerKey">The oauth consumer key.</param>
1597+ /// <param name="consumerSecret">The oauth consumer secret.</param>
1598+ /// <param name="token">The oauth token.</param>
1599+ /// <param name="tokenSecret">The oauth secret.</param>
1600+ private void PingUbuntuOneServer(string email, string consumerKey, string consumerSecret, string token, string tokenSecret)
1601+ {
1602+ // ping the service to make it download the tokens
1603+ var pingRequest = MakeRequest(Constants.PingUrl + email, "GET", consumerKey, consumerSecret,
1604+ token, tokenSecret);
1605+ try
1606+ {
1607+ pingRequest.GetResponse();
1608+ }
1609+ catch (Exception e)
1610+ {
1611+ throw new SSOException("Credentials could not be sent to Ubuntu One servers", e);
1612+ }
1613+ }
1614+
1615+ /// <summary>
1616+ /// Allows to parse the json that is returned by the rest service to extract that credentials.
1617+ /// </summary>
1618+ /// <param name="credentialsJson">Json that contains the credentials info.</param>
1619+ /// <param name="consumerKey">Out var where the oauth consumer key will be returned.</param>
1620+ /// <param name="consumerSecret">Out var where the oauth consumer secret will be returned.</param>
1621+ /// <param name="token">Out var where the oauth token secret will be returned.</param>
1622+ /// <param name="tokenSecret">Out var where the oauth token secret will be returned.</param>
1623+ private static void ParseCredentials(string credentialsJson, out string consumerKey, out string consumerSecret, out string token,
1624+ out string tokenSecret)
1625+ {
1626+ var credentials = JObject.Parse(credentialsJson);
1627+ try
1628+ {
1629+ consumerKey = (string)credentials["consumer_key"];
1630+ consumerSecret = (string)credentials["consumer_secret"];
1631+ token = (string)credentials["token"];
1632+ tokenSecret = (string)credentials["token_secret"];
1633+
1634+ }
1635+ catch (InvalidCastException e)
1636+ {
1637+ // could happen when the json is not formatted as we expected.
1638+ throw new SSOLoginException("Error when retrieving credentials.", e);
1639+ }
1640+ if (string.IsNullOrEmpty(consumerKey)
1641+ || string.IsNullOrEmpty(consumerSecret)
1642+ || string.IsNullOrEmpty(token)
1643+ || string.IsNullOrEmpty(tokenSecret))
1644+ {
1645+ // none of them can be null or empty.
1646+ throw new SSOLoginException("Credentials have missing values..");
1647+ }
1648+
1649+ }
1650+ #endregion
1651+
1652 #region Implementation of ISSOLoginProcessor
1653
1654 /// <summary>
1655@@ -61,7 +185,36 @@
1656 /// <returns>A string with the sso credentials.</returns>
1657 public string Login(string email, string password, string tokenName)
1658 {
1659- throw new NotImplementedException();
1660+ var secret = Keyring.GetSecretByName(KeyringName, ApplicationName);
1661+ if (secret == null)
1662+ {
1663+ try
1664+ {
1665+ // credentials are not present in the keyring, therefore we will have to get them from the
1666+ // rest service
1667+ string token;
1668+ string tokenSecret;
1669+ string consumerKey;
1670+ string consumerSecret;
1671+
1672+ // the rest server returns json, we need to parse it.
1673+ ParseCredentials(Authentications.Authenticate(email, password, tokenName),
1674+ out consumerKey, out consumerSecret, out token, out tokenSecret);
1675+ secret = SSOCredentialsEncoder.Encode(token, tokenSecret, consumerKey, consumerSecret);
1676+ // ping the service to make it download the tokens
1677+ PingUbuntuOneServer(email, consumerKey, consumerKey, token, tokenSecret);
1678+ Keyring.CreateSecret(KeyringName, ApplicationName, secret);
1679+ }
1680+ catch (WebException e)
1681+ {
1682+ throw new SSOLoginException("Unable to login", e);
1683+ }
1684+ catch (Exception e)
1685+ {
1686+ throw new SSOLoginException("Unable to login", e);
1687+ }
1688+ }
1689+ return secret;
1690 }
1691
1692 /// <summary>
1693
1694=== modified file 'src/Canonical.UbuntuOne.Client/Notification/NotificationIconPresenter.cs'
1695--- src/Canonical.UbuntuOne.Client/Notification/NotificationIconPresenter.cs 2010-10-05 09:58:34 +0000
1696+++ src/Canonical.UbuntuOne.Client/Notification/NotificationIconPresenter.cs 2010-10-05 09:58:35 +0000
1697@@ -1,25 +1,25 @@
1698-// Copyright 2010 Canonical Ltd.
1699-//
1700-// This file is part of UbuntuOne on Windows.
1701-//
1702-// UbuntuOne on Windows is free software: you can redistribute it and/or modify
1703-// it under the terms of the GNU Lesser General Public License version
1704-// as published by the Free Software Foundation.
1705-//
1706-// Ubuntu One on Windows is distributed in the hope that it will be useful,
1707-// but WITHOUT ANY WARRANTY; without even the implied warranty of
1708-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1709-// GNU Lesser General Public License for more details.
1710-//
1711-// You should have received a copy of the GNU Lesser General Public License
1712-// along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
1713-//
1714-// Authors: Manuel de la Peña <manuel.delapena@canonical.com>
1715+/* Copyright 2010 Canonical Ltd.
1716+ *
1717+ * This file is part of UbuntuOne on Windows.
1718+ *
1719+ * UbuntuOne on Windows is free software: you can redistribute it and/or modify
1720+ * it under the terms of the GNU Lesser General Public License version
1721+ * as published by the Free Software Foundation.
1722+ *
1723+ * Ubuntu One on Windows is distributed in the hope that it will be useful,
1724+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1725+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1726+ * GNU Lesser General Public License for more details.
1727+ *
1728+ * You should have received a copy of the GNU Lesser General Public License
1729+ * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
1730+ *
1731+ * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
1732+ */
1733 using System;
1734 using System.Diagnostics;
1735 using System.IO;
1736 using System.Net;
1737-using System.Web;
1738 using System.Windows;
1739 using Canonical.Ubuntu.SSO;
1740 using Canonical.Ubuntu.SSO.Service;
1741@@ -29,7 +29,6 @@
1742 using Canonical.UbuntuOne.Common.Utils;
1743 using log4net;
1744 using Newtonsoft.Json.Linq;
1745-using OAuth;
1746
1747 namespace Canonical.UbuntuOne.Client.Notification
1748 {
1749@@ -148,33 +147,23 @@
1750
1751 #region Helper methods
1752
1753- public HttpWebRequest MakeRequest(string uri, string consumerKey, string consumerSecret, string toke, string tokenSecret)
1754+ public HttpWebRequest MakeRequest(string uri, string consumerKey, string consumerSecret, string token, string tokenSecret)
1755 {
1756 // Form the full REST request url
1757 Uri url = new Uri(uri);
1758
1759 // Instantiate OAuthBase and declare variables
1760- var oAuth = new OAuthBase();
1761- var nonce = oAuth.GenerateNonce();
1762- var timeStamp = oAuth.GenerateTimeStamp();
1763+ var oAuth = new OAuth();
1764+
1765 var normUrl = string.Empty;
1766 var normParams = string.Empty;
1767- var strRequest = string.Empty;
1768
1769- // Create an OAuth signature
1770- string signature = oAuth.GenerateSignature(url,
1771- consumerKey, consumerSecret, toke, tokenSecret,
1772- "GET", timeStamp, nonce, OAuthBase.SignatureTypes.HMACSHA1,
1773+ var authHeader = oAuth.GenerateHeaderWithSignature(url, string.Empty, consumerKey, consumerSecret,
1774+ token, tokenSecret, "GET", oAuth.GenerateTimeStamp(), oAuth.GenerateNonce(), OAuth.SignatureTypes.HMACSHA1,
1775 out normUrl, out normParams);
1776-
1777- // Construct the OAuth authenticated REST url
1778- strRequest = normParams + "&" + HttpUtility.UrlEncode("oauth_signature") + "=" + HttpUtility.UrlEncode(signature);
1779- strRequest = strRequest.Replace("&", @""",");
1780- strRequest = strRequest.Replace("=", @"=""");
1781- strRequest += @"""";
1782- strRequest = @"OAuth realm=""""," + strRequest;
1783+
1784 var request = WebRequest.Create(normUrl) as HttpWebRequest;
1785- request.Headers.Add("Authorization", strRequest);
1786+ request.Headers.Add(authHeader.Key, authHeader.Value);
1787 return request;
1788 }
1789
1790
1791=== modified file 'src/Canonical.UbuntuOne.Common/Canonical.UbuntuOne.Common.csproj'
1792--- src/Canonical.UbuntuOne.Common/Canonical.UbuntuOne.Common.csproj 2010-08-30 17:30:31 +0000
1793+++ src/Canonical.UbuntuOne.Common/Canonical.UbuntuOne.Common.csproj 2010-10-05 09:58:35 +0000
1794@@ -57,6 +57,10 @@
1795 <Compile Include="Container\ObjectsContainer.cs" />
1796 <Compile Include="Container\SpringContainer.cs" />
1797 <Compile Include="Container\UnsatisfiedDependencyException.cs" />
1798+ <Compile Include="Net\HttpWebRequest.cs" />
1799+ <Compile Include="Net\HttpWebRequestFactory.cs" />
1800+ <Compile Include="Net\IHttpWebRequestFactory.cs" />
1801+ <Compile Include="Net\IHttpWebRequest.cs" />
1802 <Compile Include="OperationContracts\IEventNotifier.cs" />
1803 <Compile Include="Security\IAuthentication.cs" />
1804 <Compile Include="Threading\IDispatcher.cs" />
1805
1806=== added directory 'src/Canonical.UbuntuOne.Common/Net'
1807=== added file 'src/Canonical.UbuntuOne.Common/Net/HttpWebRequest.cs'
1808--- src/Canonical.UbuntuOne.Common/Net/HttpWebRequest.cs 1970-01-01 00:00:00 +0000
1809+++ src/Canonical.UbuntuOne.Common/Net/HttpWebRequest.cs 2010-10-05 09:58:35 +0000
1810@@ -0,0 +1,505 @@
1811+/*
1812+ * Copyright 2010 Canonical Ltd.
1813+ *
1814+ * This file is part of UbuntuOne on Windows.
1815+ *
1816+ * UbuntuOne on Windows is free software: you can redistribute it and/or modify
1817+ * it under the terms of the GNU Lesser General Public License version
1818+ * as published by the Free Software Foundation.
1819+ *
1820+ * Ubuntu One on Windows is distributed in the hope that it will be useful,
1821+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1822+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1823+ * GNU Lesser General Public License for more details.
1824+ *
1825+ * You should have received a copy of the GNU Lesser General Public License
1826+ * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
1827+ *
1828+ * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
1829+ */
1830+using System;
1831+using System.IO;
1832+using System.Net;
1833+using System.Net.Cache;
1834+using System.Net.Security;
1835+using System.Security.Cryptography.X509Certificates;
1836+using System.Security.Principal;
1837+using RealHttpRequest = System.Net.HttpWebRequest;
1838+
1839+namespace Canonical.UbuntuOne.Common.Net
1840+{
1841+ /// <summary>
1842+ /// Wrapper around the System.Net.HttpWebRequest.
1843+ /// </summary>
1844+ internal class HttpWebRequest : IHttpWebRequest
1845+ {
1846+ #region Variables
1847+
1848+ private RealHttpRequest _request;
1849+
1850+ #endregion
1851+
1852+ #region Constructors
1853+
1854+ /// <summary>
1855+ /// Internal constructor that can only be used by a httpweb request factory.
1856+ /// </summary>
1857+ /// <param name="httpWebRequest"></param>
1858+ internal HttpWebRequest(RealHttpRequest httpWebRequest)
1859+ {
1860+ _request = httpWebRequest;
1861+ }
1862+
1863+ #endregion
1864+
1865+ #region Implementation of IHttpWebRequest
1866+
1867+ /// <summary>
1868+ /// Gets and sets value of the Accept HTTP header. The default value is null.
1869+ /// </summary>
1870+ public string Accept
1871+ {
1872+ get { return _request.Accept; }
1873+ set { _request.Accept = value; }
1874+ }
1875+
1876+ /// <summary>
1877+ /// Gets and sets the uri that responds to the request.
1878+ /// </summary>
1879+ public Uri Address
1880+ {
1881+ get { return _request.Address; }
1882+ }
1883+
1884+ /// <summary>
1885+ /// Gets and sets if the request should automatically follow redirection responses
1886+ /// </summary>
1887+ public bool AllowAutoRedirect
1888+ {
1889+ get { return _request.AllowAutoRedirect; }
1890+ set { _request.AllowAutoRedirect = value; }
1891+ }
1892+
1893+ /// <summary>
1894+ /// Enables buffering of the data sent to the Internet resource
1895+ /// </summary>
1896+ public bool AllowWriteStreamBuffering
1897+ {
1898+ get { return _request.AllowWriteStreamBuffering; }
1899+ set { _request.AllowWriteStreamBuffering = value; }
1900+ }
1901+
1902+ /// <summary>
1903+ /// Gets and sets the auhentication lavel used.
1904+ /// </summary>
1905+ public AuthenticationLevel AuthenticationLevel
1906+ {
1907+ get { return _request.AuthenticationLevel; }
1908+ set { _request.AuthenticationLevel = value; }
1909+ }
1910+
1911+ /// <summary>
1912+ /// Gets and sets the type of decompression that is used.
1913+ /// </summary>
1914+ public DecompressionMethods AutomaticDecompression
1915+ {
1916+ get { return _request.AutomaticDecompression; }
1917+ set { _request.AutomaticDecompression = value; }
1918+ }
1919+
1920+ /// <summary>
1921+ /// Gets or sets the cache policy used by the request.
1922+ /// </summary>
1923+ public RequestCachePolicy CachePolicy
1924+ {
1925+ get { return _request.CachePolicy; }
1926+ set { _request.CachePolicy = value; }
1927+ }
1928+
1929+ /// <summary>
1930+ /// Gets and sets the certificates used by the request.
1931+ /// </summary>
1932+ public X509CertificateCollection ClientCertificates
1933+ {
1934+ get { return _request.ClientCertificates; }
1935+ set { _request.ClientCertificates = value; }
1936+ }
1937+
1938+ /// <summary>
1939+ /// Gets and sets the Connection HTTP header
1940+ /// </summary>
1941+ public string Connection
1942+ {
1943+ get { return _request.Connection; }
1944+ set { _request.Connection = value; }
1945+ }
1946+
1947+ /// <summary>
1948+ /// Gets and sets the name of the connection group for this request
1949+ /// </summary>
1950+ public string ConnectionGroupName
1951+ {
1952+ get { return _request.ConnectionGroupName; }
1953+ set { _request.ConnectionGroupName = value; }
1954+ }
1955+
1956+ /// <summary>
1957+ /// Gets and sets the number of bytes of data to send to the Internet resource.
1958+ /// </summary>
1959+ public long ContentLength
1960+ {
1961+ get { return _request.ContentLength; }
1962+ set { _request.ContentLength = value; }
1963+ }
1964+
1965+ /// <summary>
1966+ /// Gets and sets the content type of the request.
1967+ /// </summary>
1968+ public string ContentType
1969+ {
1970+ get { return _request.ContentType; }
1971+ set { _request.ContentType = value; }
1972+ }
1973+
1974+ /// <summary>
1975+ /// Gets and sets the delegate that implements the callback method that
1976+ /// executes when an HTTP Continue response is returned from the Internet resource.
1977+ /// </summary>
1978+ public HttpContinueDelegate ContinueDelegate
1979+ {
1980+ get { return _request.ContinueDelegate; }
1981+ set { _request.ContinueDelegate = value; }
1982+ }
1983+
1984+ /// <summary>
1985+ /// Gets and sets cookies container associated with this request.
1986+ /// </summary>
1987+ public CookieContainer CookieContainer
1988+ {
1989+ get { return _request.CookieContainer; }
1990+ set { _request.CookieContainer = value; }
1991+ }
1992+
1993+ /// <summary>
1994+ /// Gets and sets the credentials used with the request.
1995+ /// </summary>
1996+ public ICredentials Credentials
1997+ {
1998+ get { return _request.Credentials; }
1999+ set { _request.Credentials = value; }
2000+ }
2001+
2002+ /// <summary>
2003+ /// Gets and sets the data header of the request.
2004+ /// </summary>
2005+ public DateTime Date
2006+ {
2007+ get { throw new NotImplementedException(); }
2008+ set { throw new NotImplementedException(); }
2009+ }
2010+
2011+ /// <summary>
2012+ /// Gets and sets the Expect HTTP header.
2013+ /// </summary>
2014+ public string Expect
2015+ {
2016+ get { return _request.Expect; }
2017+ set { _request.Expect = value; }
2018+ }
2019+
2020+ /// <summary>
2021+ /// Gets if a response has been received.
2022+ /// </summary>
2023+ public bool HaveResponse
2024+ {
2025+ get { return _request.HaveResponse; }
2026+ }
2027+
2028+ /// <summary>
2029+ /// Gets and sets the headers of the request,
2030+ /// </summary>
2031+ public WebHeaderCollection Headers
2032+ {
2033+ get { return _request.Headers; }
2034+ set { _request.Headers = value; }
2035+ }
2036+
2037+ /// <summary>
2038+ /// Gets and sets the Host header.
2039+ /// </summary>
2040+ public string Host
2041+ {
2042+ get { throw new NotImplementedException(); }
2043+ set { throw new NotImplementedException(); }
2044+ }
2045+
2046+ /// <summary>
2047+ /// A DateTime that contains the contents of the If-Modified-Since HTTP header.
2048+ /// </summary>
2049+ public DateTime IfModifiedSince
2050+ {
2051+ get { return _request.IfModifiedSince; }
2052+ set { _request.IfModifiedSince = value; }
2053+ }
2054+
2055+ /// <summary>
2056+ /// Gets and sets the the impersonation level.
2057+ /// </summary>
2058+ public TokenImpersonationLevel ImpersonationLevel
2059+ {
2060+ get { return _request.ImpersonationLevel; }
2061+ set { _request.ImpersonationLevel = value; }
2062+ }
2063+
2064+ /// <summary>
2065+ /// Gets and sets if the request should have a Connection HTTP header.
2066+ /// </summary>
2067+ public bool KeepAlive
2068+ {
2069+ get { return _request.KeepAlive; }
2070+ set { _request.KeepAlive = value; }
2071+ }
2072+
2073+ /// <summary>
2074+ /// Gets and sets the max number of redirections.
2075+ /// </summary>
2076+ public int MaximumAutomaticRedirections
2077+ {
2078+ get { return _request.MaximumAutomaticRedirections; }
2079+ set { _request.MaximumAutomaticRedirections = value; }
2080+ }
2081+
2082+ /// <summary>
2083+ /// Gets and sets The length, in kilobytes (1024 bytes), of the response headers.
2084+ /// </summary>
2085+ public int MaximumResponseHeadersLength
2086+ {
2087+ get { return _request.MaximumResponseHeadersLength; }
2088+ set { _request.MaximumResponseHeadersLength = value; }
2089+ }
2090+
2091+ /// <summary>
2092+ /// The media type of the request.
2093+ /// </summary>
2094+ public string MediaType
2095+ {
2096+ get { return _request.MediaType; }
2097+ set { _request.MediaType = value; }
2098+ }
2099+
2100+ /// <summary>
2101+ /// Gets and sets the request method.
2102+ /// </summary>
2103+ public string Method
2104+ {
2105+ get { return _request.Method; }
2106+ set { _request.Method = value; }
2107+ }
2108+
2109+ /// <summary>
2110+ /// Gets and sets if the request should be pipelined
2111+ /// </summary>
2112+ public bool Pipelined
2113+ {
2114+ get { return _request.Pipelined; }
2115+ set { _request.Pipelined = value; }
2116+ }
2117+
2118+ /// <summary>
2119+ /// Gets and sets if an HTTP Authorization header with requests after authentication has taken place;
2120+ /// </summary>
2121+ public bool PreAuthenticate
2122+ {
2123+ get { return _request.PreAuthenticate; }
2124+ set { _request.PreAuthenticate = value; }
2125+ }
2126+
2127+ /// <summary>
2128+ /// Gets and sets the protol version used.
2129+ /// </summary>
2130+ public Version ProtocolVersion
2131+ {
2132+ get { return _request.ProtocolVersion; }
2133+ set { _request.ProtocolVersion = value; }
2134+ }
2135+
2136+ /// <summary>
2137+ /// Gets and sets the proxy information.
2138+ /// </summary>
2139+ public IWebProxy Proxy
2140+ {
2141+ get { return _request.Proxy; }
2142+ set { _request.Proxy = value; }
2143+ }
2144+
2145+ /// <summary>
2146+ /// Gets and sets the number of milliseconds before the writing or reading times out..
2147+ /// </summary>
2148+ public int ReadWriteTimeout
2149+ {
2150+ get { return _request.ReadWriteTimeout; }
2151+ set { _request.ReadWriteTimeout = value; }
2152+ }
2153+
2154+ /// <summary>
2155+ /// Gets and sets the Referer HTTP header.
2156+ /// </summary>
2157+ public string Referer
2158+ {
2159+ get { return _request.Referer; }
2160+ set { _request.Referer = value; }
2161+ }
2162+
2163+ /// <summary>
2164+ /// Gets the resource uri used by the request.
2165+ /// </summary>
2166+ public Uri RequestUri
2167+ {
2168+ get { return _request.RequestUri; }
2169+ }
2170+
2171+ /// <summary>
2172+ /// Ges and sets if the request should be sent in chuckes.
2173+ /// </summary>
2174+ public bool SendChunked
2175+ {
2176+ get { return _request.SendChunked; }
2177+ set { _request.SendChunked = value; }
2178+ }
2179+
2180+ /// <summary>
2181+ /// Gets the service point that represents the internet resource.
2182+ /// </summary>
2183+ public ServicePoint ServicePoint
2184+ {
2185+ get { return _request.ServicePoint; }
2186+ }
2187+
2188+ /// <summary>
2189+ /// Gets and sets the number of milliseconds to wait before the request times out.
2190+ /// </summary>
2191+ public int Timeout
2192+ {
2193+ get { return _request.Timeout; }
2194+ set { _request.Timeout = value; }
2195+ }
2196+
2197+ /// <summary>
2198+ /// Gets and sets the Transfer-encoding HTTP header.
2199+ /// </summary>
2200+ public string TransferEncoding
2201+ {
2202+ get { return _request.TransferEncoding; }
2203+ set { _request.TransferEncoding = value; }
2204+ }
2205+
2206+ /// <summary>
2207+ /// Gets and sets if the authenticated connection is kept opened.
2208+ /// </summary>
2209+ public bool UnsafeAuthenticatedConnectionSharing
2210+ {
2211+ get { return _request.UnsafeAuthenticatedConnectionSharing; }
2212+ set { _request.UnsafeAuthenticatedConnectionSharing = value; }
2213+ }
2214+
2215+ /// <summary>
2216+ /// Gets and sets if the default credentials are used.
2217+ /// </summary>
2218+ public bool UseDefaultCredentials
2219+ {
2220+ get { return _request.UseDefaultCredentials; }
2221+ set { _request.UseDefaultCredentials = value; }
2222+ }
2223+
2224+ /// <summary>
2225+ /// Gets or sets the User-agent HTTP header;
2226+ /// </summary>
2227+ public string UserAgent
2228+ {
2229+ get { return _request.UserAgent; }
2230+ set { _request.UserAgent = value; }
2231+ }
2232+
2233+ /// <summary>
2234+ /// Cancels a request to a resource
2235+ /// </summary>
2236+ public void Abort()
2237+ {
2238+ _request.Abort();
2239+ }
2240+
2241+ /// <summary>
2242+ /// Begins an asynchronous request for a Stream object to use to write data.
2243+ /// </summary>
2244+ /// <param name="callback">The delegate to execute.</param>
2245+ /// <param name="state">Teh state object of the request. </param>
2246+ /// <returns>An async result.</returns>
2247+ public IAsyncResult BeginGetRequestStream(AsyncCallback callback, object state)
2248+ {
2249+ return _request.BeginGetRequestStream(callback, state);
2250+ }
2251+
2252+ /// <summary>
2253+ /// Begins an asynchronous request to an Internet resource.
2254+ /// </summary>
2255+ /// <param name="callback">Teh deleaget.</param>
2256+ /// <param name="state">Teh state object fo the response.</param>
2257+ /// <returns>an asyn result.</returns>
2258+ public IAsyncResult BeginGetResponse(AsyncCallback callback, object state)
2259+ {
2260+ return _request.BeginGetResponse(callback, state);
2261+ }
2262+
2263+ /// <summary>
2264+ /// Ends an asynchronous request for a Stream object to use to write data.
2265+ /// </summary>
2266+ /// <param name="asyncResult">The result from the async request.</param>
2267+ /// <returns>Teh stream from teh request.</returns>
2268+ public Stream EndGetRequestStream(IAsyncResult asyncResult)
2269+ {
2270+ return EndGetRequestStream(asyncResult);
2271+ }
2272+
2273+ /// <summary>
2274+ /// Ends an asynchronous request for a Stream object to use to write data and outputs
2275+ /// the TransportContext associated with the stream.
2276+ /// </summary>
2277+ /// <param name="asyncResult">The async result from the request stream.</param>
2278+ /// <param name="context">The context of the request.</param>
2279+ /// <returns>The request stream.</returns>
2280+ public Stream EndGetRequestStream(IAsyncResult asyncResult, out TransportContext context)
2281+ {
2282+ return _request.EndGetRequestStream(asyncResult, out context);
2283+ }
2284+
2285+ /// <summary>
2286+ /// Ends an asynchronous request to an Internet resource.
2287+ /// </summary>
2288+ /// <param name="asyncResult">The async result from the asyn response.</param>
2289+ /// <returns>Teh response frm the internet resource.</returns>
2290+ public WebResponse EndGetResponse(IAsyncResult asyncResult)
2291+ {
2292+ return _request.EndGetResponse(asyncResult);
2293+ }
2294+
2295+ /// <summary>
2296+ /// Gets a Stream object to use to write request data.
2297+ /// </summary>
2298+ /// <returns>Teh stream to which write the request.</returns>
2299+ public Stream GetRequestStream()
2300+ {
2301+ return _request.GetRequestStream();
2302+ }
2303+
2304+ /// <summary>
2305+ /// Returns a response from an Internet resource.
2306+ /// </summary>
2307+ /// <returns>Teh response from the resource.</returns>
2308+ public WebResponse GetResponse()
2309+ {
2310+ return _request.GetResponse();
2311+ }
2312+
2313+ #endregion
2314+ }
2315+}
2316
2317=== added file 'src/Canonical.UbuntuOne.Common/Net/HttpWebRequestFactory.cs'
2318--- src/Canonical.UbuntuOne.Common/Net/HttpWebRequestFactory.cs 1970-01-01 00:00:00 +0000
2319+++ src/Canonical.UbuntuOne.Common/Net/HttpWebRequestFactory.cs 2010-10-05 09:58:35 +0000
2320@@ -0,0 +1,59 @@
2321+/*
2322+ * Copyright 2010 Canonical Ltd.
2323+ *
2324+ * This file is part of UbuntuOne on Windows.
2325+ *
2326+ * UbuntuOne on Windows is free software: you can redistribute it and/or modify
2327+ * it under the terms of the GNU Lesser General Public License version
2328+ * as published by the Free Software Foundation.
2329+ *
2330+ * Ubuntu One on Windows is distributed in the hope that it will be useful,
2331+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2332+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2333+ * GNU Lesser General Public License for more details.
2334+ *
2335+ * You should have received a copy of the GNU Lesser General Public License
2336+ * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
2337+ *
2338+ * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
2339+ */
2340+using System;
2341+using System.Net;
2342+using RealHttpRequest = System.Net.HttpWebRequest;
2343+
2344+namespace Canonical.UbuntuOne.Common.Net
2345+{
2346+ /// <summary>
2347+ /// Class that creates IHttpWebRequest that can be used to request an internet resource.
2348+ /// </summary>
2349+ internal class HttpWebRequestFactory : IHttpWebRequestFactory
2350+ {
2351+ #region Implementation of IHttpWebRequestFactory
2352+
2353+ /// <summary>
2354+ /// Creates a new webrequest that will be used to request an internet resource that is identified
2355+ /// by the given uri.
2356+ /// </summary>
2357+ /// <param name="uri">A string with the uri that identifies the internet resource.</param>
2358+ /// <returns>An IHttpWebRequest that can be used to request an internet resource.</returns>
2359+ public IHttpWebRequest Create(string uri)
2360+ {
2361+ var realRequest = WebRequest.Create(uri) as RealHttpRequest;
2362+ return new HttpWebRequest(realRequest);
2363+ }
2364+
2365+ /// <summary>
2366+ /// Creates a webrequest that will be used to request an internet resource that is identified by
2367+ /// the given uri.
2368+ /// </summary>
2369+ /// <param name="uri">An object that identifies the web request.</param>
2370+ /// <returns>An HttpWebRequest that can be used to request an internet resource.</returns>
2371+ public IHttpWebRequest Create(Uri uri)
2372+ {
2373+ var realRequest = WebRequest.Create(uri) as RealHttpRequest;
2374+ return new HttpWebRequest(realRequest);
2375+ }
2376+
2377+ #endregion
2378+ }
2379+}
2380
2381=== added file 'src/Canonical.UbuntuOne.Common/Net/IHttpWebRequest.cs'
2382--- src/Canonical.UbuntuOne.Common/Net/IHttpWebRequest.cs 1970-01-01 00:00:00 +0000
2383+++ src/Canonical.UbuntuOne.Common/Net/IHttpWebRequest.cs 2010-10-05 09:58:35 +0000
2384@@ -0,0 +1,297 @@
2385+/*
2386+ * Copyright 2010 Canonical Ltd.
2387+ *
2388+ * This file is part of UbuntuOne on Windows.
2389+ *
2390+ * UbuntuOne on Windows is free software: you can redistribute it and/or modify
2391+ * it under the terms of the GNU Lesser General Public License version
2392+ * as published by the Free Software Foundation.
2393+ *
2394+ * Ubuntu One on Windows is distributed in the hope that it will be useful,
2395+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2396+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2397+ * GNU Lesser General Public License for more details.
2398+ *
2399+ * You should have received a copy of the GNU Lesser General Public License
2400+ * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
2401+ *
2402+ * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
2403+ */
2404+using System;
2405+using System.IO;
2406+using System.Net;
2407+using System.Net.Cache;
2408+using System.Net.Security;
2409+using System.Security.Cryptography.X509Certificates;
2410+using System.Security.Principal;
2411+
2412+namespace Canonical.UbuntuOne.Common.Net
2413+{
2414+ /// <summary>
2415+ /// Helper interface that wrapps the HttpWebRequest class from System.Net
2416+ /// </summary>
2417+ public interface IHttpWebRequest
2418+ {
2419+ /// <summary>
2420+ /// Gets and sets value of the Accept HTTP header. The default value is null.
2421+ /// </summary>
2422+ string Accept { get; set; }
2423+
2424+ /// <summary>
2425+ /// Gets and sets the uri that responds to the request.
2426+ /// </summary>
2427+ Uri Address { get; }
2428+
2429+ /// <summary>
2430+ /// Gets and sets if the request should automatically follow redirection responses
2431+ /// </summary>
2432+ bool AllowAutoRedirect { get; set; }
2433+
2434+ /// <summary>
2435+ /// Enables buffering of the data sent to the Internet resource
2436+ /// </summary>
2437+ bool AllowWriteStreamBuffering { get; set; }
2438+
2439+ /// <summary>
2440+ /// Gets and sets the auhentication lavel used.
2441+ /// </summary>
2442+ AuthenticationLevel AuthenticationLevel { get; set; }
2443+
2444+ /// <summary>
2445+ /// Gets and sets the type of decompression that is used.
2446+ /// </summary>
2447+ DecompressionMethods AutomaticDecompression { get; set; }
2448+
2449+ /// <summary>
2450+ /// Gets or sets the cache policy used by the request.
2451+ /// </summary>
2452+ RequestCachePolicy CachePolicy { get; set; }
2453+
2454+ /// <summary>
2455+ /// Gets and sets the certificates used by the request.
2456+ /// </summary>
2457+ X509CertificateCollection ClientCertificates { get; set; }
2458+
2459+ /// <summary>
2460+ /// Gets and sets the Connection HTTP header
2461+ /// </summary>
2462+ string Connection { get; set; }
2463+
2464+ /// <summary>
2465+ /// Gets and sets the name of the connection group for this request
2466+ /// </summary>
2467+ string ConnectionGroupName { get; set; }
2468+
2469+ /// <summary>
2470+ /// Gets and sets the number of bytes of data to send to the Internet resource.
2471+ /// </summary>
2472+ long ContentLength { get; set; }
2473+
2474+ /// <summary>
2475+ /// Gets and sets the content type of the request.
2476+ /// </summary>
2477+ string ContentType { get; set; }
2478+
2479+ /// <summary>
2480+ /// Gets and sets the delegate that implements the callback method that
2481+ /// executes when an HTTP Continue response is returned from the Internet resource.
2482+ /// </summary>
2483+ HttpContinueDelegate ContinueDelegate { get; set; }
2484+
2485+ /// <summary>
2486+ /// Gets and sets cookies container associated with this request.
2487+ /// </summary>
2488+ CookieContainer CookieContainer { get; set; }
2489+
2490+ /// <summary>
2491+ /// Gets and sets the credentials used with the request.
2492+ /// </summary>
2493+ ICredentials Credentials { get; set; }
2494+
2495+ /// <summary>
2496+ /// Gets and sets the data header of the request.
2497+ /// </summary>
2498+ DateTime Date { get; set; }
2499+
2500+ /// <summary>
2501+ /// Gets and sets the Expect HTTP header.
2502+ /// </summary>
2503+ string Expect { get; set; }
2504+
2505+ /// <summary>
2506+ /// Gets if a response has been received.
2507+ /// </summary>
2508+ bool HaveResponse { get; }
2509+
2510+ /// <summary>
2511+ /// Gets and sets the headers of the request,
2512+ /// </summary>
2513+ WebHeaderCollection Headers { get; set; }
2514+
2515+ /// <summary>
2516+ /// Gets and sets the Host header.
2517+ /// </summary>
2518+ string Host { get; set; }
2519+
2520+ /// <summary>
2521+ /// A DateTime that contains the contents of the If-Modified-Since HTTP header.
2522+ /// </summary>
2523+ DateTime IfModifiedSince { get; set; }
2524+
2525+ /// <summary>
2526+ /// Gets and sets the the impersonation level.
2527+ /// </summary>
2528+ TokenImpersonationLevel ImpersonationLevel { get; set; }
2529+
2530+ /// <summary>
2531+ /// Gets and sets if the request should have a Connection HTTP header.
2532+ /// </summary>
2533+ bool KeepAlive { get; set; }
2534+
2535+ /// <summary>
2536+ /// Gets and sets the max number of redirections.
2537+ /// </summary>
2538+ int MaximumAutomaticRedirections { get; set; }
2539+
2540+ /// <summary>
2541+ /// Gets and sets The length, in kilobytes (1024 bytes), of the response headers.
2542+ /// </summary>
2543+ int MaximumResponseHeadersLength { get; set; }
2544+
2545+ /// <summary>
2546+ /// The media type of the request.
2547+ /// </summary>
2548+ string MediaType { get; set; }
2549+
2550+ /// <summary>
2551+ /// Gets and sets the request method.
2552+ /// </summary>
2553+ string Method { get; set; }
2554+
2555+ /// <summary>
2556+ /// Gets and sets if the request should be pipelined
2557+ /// </summary>
2558+ bool Pipelined { get; set; }
2559+
2560+ /// <summary>
2561+ /// Gets and sets if an HTTP Authorization header with requests after authentication has taken place;
2562+ /// </summary>
2563+ bool PreAuthenticate { get; set; }
2564+
2565+ /// <summary>
2566+ /// Gets and sets the protol version used.
2567+ /// </summary>
2568+ Version ProtocolVersion { get; set; }
2569+
2570+ /// <summary>
2571+ /// Gets and sets the proxy information.
2572+ /// </summary>
2573+ IWebProxy Proxy { get; set; }
2574+
2575+ /// <summary>
2576+ /// Gets and sets the number of milliseconds before the writing or reading times out..
2577+ /// </summary>
2578+ int ReadWriteTimeout { get; set; }
2579+
2580+ /// <summary>
2581+ /// Gets and sets the Referer HTTP header.
2582+ /// </summary>
2583+ string Referer { get; set; }
2584+
2585+ /// <summary>
2586+ /// Gets the resource uri used by the request.
2587+ /// </summary>
2588+ Uri RequestUri { get; }
2589+
2590+ /// <summary>
2591+ /// Ges and sets if the request should be sent in chuckes.
2592+ /// </summary>
2593+ bool SendChunked { get; set; }
2594+
2595+ /// <summary>
2596+ /// Gets the service point that represents the internet resource.
2597+ /// </summary>
2598+ ServicePoint ServicePoint { get; }
2599+
2600+ /// <summary>
2601+ /// Gets and sets the number of milliseconds to wait before the request times out.
2602+ /// </summary>
2603+ int Timeout { get; set; }
2604+
2605+ /// <summary>
2606+ /// Gets and sets the Transfer-encoding HTTP header.
2607+ /// </summary>
2608+ string TransferEncoding { get; set; }
2609+
2610+ /// <summary>
2611+ /// Gets and sets if the authenticated connection is kept opened.
2612+ /// </summary>
2613+ bool UnsafeAuthenticatedConnectionSharing { get; set; }
2614+
2615+ /// <summary>
2616+ /// Gets and sets if the default credentials are used.
2617+ /// </summary>
2618+ bool UseDefaultCredentials { get; set; }
2619+
2620+ /// <summary>
2621+ /// Gets or sets the User-agent HTTP header;
2622+ /// </summary>
2623+ string UserAgent { get; set; }
2624+
2625+ /// <summary>
2626+ /// Cancels a request to a resource
2627+ /// </summary>
2628+ void Abort();
2629+
2630+ /// <summary>
2631+ /// Begins an asynchronous request for a Stream object to use to write data.
2632+ /// </summary>
2633+ /// <param name="callback">The delegate to execute.</param>
2634+ /// <param name="state">Teh state object of the request. </param>
2635+ /// <returns>An async result.</returns>
2636+ IAsyncResult BeginGetRequestStream(AsyncCallback callback,Object state);
2637+
2638+ /// <summary>
2639+ /// Begins an asynchronous request to an Internet resource.
2640+ /// </summary>
2641+ /// <param name="callback">Teh deleaget.</param>
2642+ /// <param name="state">Teh state object fo the response.</param>
2643+ /// <returns>an asyn result.</returns>
2644+ IAsyncResult BeginGetResponse(AsyncCallback callback,Object state);
2645+
2646+ /// <summary>
2647+ /// Ends an asynchronous request for a Stream object to use to write data.
2648+ /// </summary>
2649+ /// <param name="asyncResult">The result from the async request.</param>
2650+ /// <returns>Teh stream from teh request.</returns>
2651+ Stream EndGetRequestStream(IAsyncResult asyncResult);
2652+
2653+ /// <summary>
2654+ /// Ends an asynchronous request for a Stream object to use to write data and outputs
2655+ /// the TransportContext associated with the stream.
2656+ /// </summary>
2657+ /// <param name="asyncResult">The async result from the request stream.</param>
2658+ /// <param name="context">The context of the request.</param>
2659+ /// <returns>The request stream.</returns>
2660+ Stream EndGetRequestStream(IAsyncResult asyncResult,out TransportContext context);
2661+
2662+ /// <summary>
2663+ /// Ends an asynchronous request to an Internet resource.
2664+ /// </summary>
2665+ /// <param name="asyncResult">The async result from the asyn response.</param>
2666+ /// <returns>Teh response frm the internet resource.</returns>
2667+ WebResponse EndGetResponse(IAsyncResult asyncResult);
2668+
2669+ /// <summary>
2670+ /// Gets a Stream object to use to write request data.
2671+ /// </summary>
2672+ /// <returns>Teh stream to which write the request.</returns>
2673+ Stream GetRequestStream();
2674+
2675+ /// <summary>
2676+ /// Returns a response from an Internet resource.
2677+ /// </summary>
2678+ /// <returns>Teh response from the resource.</returns>
2679+ WebResponse GetResponse();
2680+ }
2681+}
2682
2683=== added file 'src/Canonical.UbuntuOne.Common/Net/IHttpWebRequestFactory.cs'
2684--- src/Canonical.UbuntuOne.Common/Net/IHttpWebRequestFactory.cs 1970-01-01 00:00:00 +0000
2685+++ src/Canonical.UbuntuOne.Common/Net/IHttpWebRequestFactory.cs 2010-10-05 09:58:35 +0000
2686@@ -0,0 +1,45 @@
2687+/*
2688+ * Copyright 2010 Canonical Ltd.
2689+ *
2690+ * This file is part of UbuntuOne on Windows.
2691+ *
2692+ * UbuntuOne on Windows is free software: you can redistribute it and/or modify
2693+ * it under the terms of the GNU Lesser General Public License version
2694+ * as published by the Free Software Foundation.
2695+ *
2696+ * Ubuntu One on Windows is distributed in the hope that it will be useful,
2697+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2698+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2699+ * GNU Lesser General Public License for more details.
2700+ *
2701+ * You should have received a copy of the GNU Lesser General Public License
2702+ * along with UbuntuOne for Windows. If not, see <http://www.gnu.org/licenses/>.
2703+ *
2704+ * Authors: Manuel de la Peña <manuel.delapena@canonical.com>
2705+ */
2706+using System;
2707+
2708+namespace Canonical.UbuntuOne.Common.Net
2709+{
2710+ /// <summary>
2711+ /// Simple interface to be implemented by those objects that are able to create web requests.
2712+ /// </summary>
2713+ public interface IHttpWebRequestFactory
2714+ {
2715+ /// <summary>
2716+ /// Creates a new webrequest that will be used to request an internet resource that is identified
2717+ /// by the given uri.
2718+ /// </summary>
2719+ /// <param name="uri">A string with the uri that identifies the internet resource.</param>
2720+ /// <returns>An IHttpWebRequest that can be used to request an internet resource.</returns>
2721+ IHttpWebRequest Create(string uri);
2722+
2723+ /// <summary>
2724+ /// Creates a webrequest that will be used to request an internet resource that is identified by
2725+ /// the given uri.
2726+ /// </summary>
2727+ /// <param name="uri">An object that identifies the web request.</param>
2728+ /// <returns>An HttpWebRequest that can be used to request an internet resource.</returns>
2729+ IHttpWebRequest Create(Uri uri);
2730+ }
2731+}

Subscribers

People subscribed via source and target branches

to all changes: