Mercurial > altnet-hispano
changeset 109:6bd9be78caa0
Merge
author | Nelo@Kenia.neluz.int |
---|---|
date | Tue, 07 Jun 2011 23:21:07 -0300 |
parents | 786a90e26c9b (diff) 80c22175c9b5 (current diff) |
children | a456eb519e23 |
files | Agendas/trunk/src/Agendas.Twitter.Tests/Send_twitt_tests.cs |
diffstat | 13 files changed, 283 insertions(+), 652 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Agendas/trunk/src/Agendas.Twitter.Tests/Agendas.Twitter.Tests.csproj Tue Jun 07 23:21:07 2011 -0300 @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>8.0.30703</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{462D86DD-7F4D-4596-B18B-2DD92C7FD73F}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Agendas.Twitter.Tests</RootNamespace> + <AssemblyName>Agendas.Twitter.Tests</AssemblyName> + <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Newtonsoft.Json"> + <HintPath>..\packages\Newtonsoft.Json.3.5.8\lib\35\Newtonsoft.Json.dll</HintPath> + </Reference> + <Reference Include="nunit.framework"> + <HintPath>..\packages\NUnit.2.5.10.11092\lib\nunit.framework.dll</HintPath> + </Reference> + <Reference Include="nunit.mocks"> + <HintPath>..\packages\NUnit.2.5.10.11092\lib\nunit.mocks.dll</HintPath> + </Reference> + <Reference Include="pnunit.framework"> + <HintPath>..\packages\NUnit.2.5.10.11092\lib\pnunit.framework.dll</HintPath> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Xml" /> + <Reference Include="Twitterizer2"> + <HintPath>..\packages\twitterizer.2.3.2\lib\Twitterizer2.dll</HintPath> + </Reference> + </ItemGroup> + <ItemGroup> + <Compile Include="Send_twitt_tests.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <ItemGroup> + <None Include="App.config" /> + <None Include="packages.config" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\Agendas.Domain\Agendas.Domain.csproj"> + <Project>{A14907DF-02E4-4FA7-BE27-4292AF50AA22}</Project> + <Name>Agendas.Domain</Name> + </ProjectReference> + <ProjectReference Include="..\Agendas.Twitter\Agendas.Twitter.csproj"> + <Project>{D8DA7ED2-A274-4DF6-9DD2-A9DC65F4C2F5}</Project> + <Name>Agendas.Twitter</Name> + </ProjectReference> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Agendas/trunk/src/Agendas.Twitter.Tests/App.config Tue Jun 07 23:21:07 2011 -0300 @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8" ?> +<configuration> + <appSettings> + <add key="consumerKey" value="UpwG7RKRAqQfdsCKnBfHA"/> + <add key="consumerSecret" value="HIOb9tMewejyFX97mhsQO2FXSEQN4kzJFF6iQLx4k"/> + <add key="accessToken" value="301500900-1GGyiecfAgmbrJMEcjp4XA9KXEJU2bBLyEQNQL5S" /> + <add key="accessTokenSecret" value="46vNqg4djzyh9GRtZoUv0c7uEl7mQ3CjVBeJ4wwRpds"/> + </appSettings> +</configuration> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Agendas/trunk/src/Agendas.Twitter.Tests/Properties/AssemblyInfo.cs Tue Jun 07 23:21:07 2011 -0300 @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Agendas.Twitter.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("Agendas.Twitter.Tests")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("fb277dd8-af44-4be7-a300-70902bb2de61")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Agendas/trunk/src/Agendas.Twitter.Tests/Send_twitt_tests.cs Tue Jun 07 23:21:07 2011 -0300 @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using AltNetHispano.Agendas.Twitter; +using NUnit.Framework; +using Twitterizer; + +namespace Agendas.Twitter.Tests +{ + [TestFixture] + public class Send_twitt_tests + { + [Test] + public void Send_twitt() + { + var p = new TwitterPublicador(); + + string message; + var r = p.Publicar("Hello, #Twitterizer. Hora: " + DateTime.Now, out message); + + Console.WriteLine(message); + Assert.IsTrue(r); + } + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Agendas/trunk/src/Agendas.Twitter.Tests/packages.config Tue Jun 07 23:21:07 2011 -0300 @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="NUnit" version="2.5.10.11092" /> + <package id="Newtonsoft.Json" version="3.5.8" /> + <package id="twitterizer" version="2.3.2" /> +</packages> \ No newline at end of file
--- a/Agendas/trunk/src/Agendas.Twitter/Agendas.Twitter.csproj Mon Jun 06 14:07:12 2011 -0300 +++ b/Agendas/trunk/src/Agendas.Twitter/Agendas.Twitter.csproj Tue Jun 07 23:21:07 2011 -0300 @@ -31,6 +31,9 @@ <WarningLevel>4</WarningLevel> </PropertyGroup> <ItemGroup> + <Reference Include="Newtonsoft.Json"> + <HintPath>..\packages\Newtonsoft.Json.3.5.8\lib\35\Newtonsoft.Json.dll</HintPath> + </Reference> <Reference Include="System" /> <Reference Include="System.Configuration" /> <Reference Include="System.Core" /> @@ -40,10 +43,12 @@ <Reference Include="Microsoft.CSharp" /> <Reference Include="System.Data" /> <Reference Include="System.Xml" /> + <Reference Include="Twitterizer2"> + <HintPath>..\packages\twitterizer.2.3.2\lib\Twitterizer2.dll</HintPath> + </Reference> </ItemGroup> <ItemGroup> - <Compile Include="oAuth.cs" /> - <Compile Include="oAuthTwitter.cs" /> + <Compile Include="OAuthTwitter.cs" /> <Compile Include="TwitterPublicador.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> </ItemGroup> @@ -53,6 +58,9 @@ <Name>Agendas.Domain</Name> </ProjectReference> </ItemGroup> + <ItemGroup> + <None Include="packages.config" /> + </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets.
--- a/Agendas/trunk/src/Agendas.Twitter/TwitterPublicador.cs Mon Jun 06 14:07:12 2011 -0300 +++ b/Agendas/trunk/src/Agendas.Twitter/TwitterPublicador.cs Tue Jun 07 23:21:07 2011 -0300 @@ -1,14 +1,55 @@ using System; using System.Collections.Generic; +using System.Configuration; using AltNetHispano.Agendas.Domain; +using Twitterizer; namespace AltNetHispano.Agendas.Twitter { public class TwitterPublicador : IPublicador { + private string ConsumerKey + { + get { return ConfigurationManager.AppSettings["consumerKey"]; } + } + + private string ConsumerSecret + { + get { return ConfigurationManager.AppSettings["consumerSecret"]; } + } + + + private string AccessToken + { + get { return ConfigurationManager.AppSettings["accessToken"]; } + } + + + private string AccessTokenSecret + { + get { return ConfigurationManager.AppSettings["accessTokenSecret"]; } + } + public void Publicar(IEnumerable<Track> tracks) { throw new NotImplementedException(); } + + public bool Publicar (string status, out string message) + { + var tokens = new OAuthTokens + { + ConsumerKey = ConsumerKey, + ConsumerSecret = ConsumerSecret, + AccessToken = AccessToken, + AccessTokenSecret = AccessTokenSecret + }; + + var response = TwitterStatus.Update(tokens, status); + + message = response.ErrorMessage; + return response.Result == RequestResult.Success; + + } } } \ No newline at end of file
--- a/Agendas/trunk/src/Agendas.Twitter/oAuth.cs Mon Jun 06 14:07:12 2011 -0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,373 +0,0 @@ -using System; -using System.Security.Cryptography; -using System.Collections.Generic; -using System.Text; -using System.Web; - -namespace AltNetHispano.Agendas.Twitter -{ - public class OAuthBase - { - - /// <summary> - /// Provides a predefined set of algorithms that are supported officially by the protocol - /// </summary> - public enum SignatureTypes - { - HMACSHA1, - PLAINTEXT, - RSASHA1 - } - - /// <summary> - /// Provides an internal structure to sort the query parameter - /// </summary> - protected class QueryParameter - { - private string name = null; - private string value = null; - - public QueryParameter(string name, string value) - { - this.name = name; - this.value = value; - } - - public string Name - { - get { return name; } - } - - public string Value - { - get { return value; } - } - } - - /// <summary> - /// Comparer class used to perform the sorting of the query parameters - /// </summary> - protected class QueryParameterComparer : IComparer<QueryParameter> - { - - #region IComparer<QueryParameter> Members - - public int Compare(QueryParameter x, QueryParameter y) - { - if (x.Name == y.Name) - { - return string.Compare(x.Value, y.Value); - } - else - { - return string.Compare(x.Name, y.Name); - } - } - - #endregion - } - - protected const string OAuthVersion = "1.0"; - protected const string OAuthParameterPrefix = "oauth_"; - - // - // List of know and used oauth parameters' names - // - protected const string OAuthConsumerKeyKey = "oauth_consumer_key"; - protected const string OAuthCallbackKey = "oauth_callback"; - protected const string OAuthVersionKey = "oauth_version"; - protected const string OAuthSignatureMethodKey = "oauth_signature_method"; - protected const string OAuthSignatureKey = "oauth_signature"; - protected const string OAuthTimestampKey = "oauth_timestamp"; - protected const string OAuthNonceKey = "oauth_nonce"; - protected const string OAuthTokenKey = "oauth_token"; - protected const string OAuthTokenSecretKey = "oauth_token_secret"; - protected const string OAuthVerifierKey = "oauth_verifier"; - - protected const string HMACSHA1SignatureType = "HMAC-SHA1"; - protected const string PlainTextSignatureType = "PLAINTEXT"; - protected const string RSASHA1SignatureType = "RSA-SHA1"; - - protected Random random = new Random(); - - protected string unreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~"; - - /// <summary> - /// Helper function to compute a hash value - /// </summary> - /// <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> - /// <param name="data">The data to hash</param> - /// <returns>a Base64 string of the hash value</returns> - private string ComputeHash(HashAlgorithm hashAlgorithm, string data) - { - if (hashAlgorithm == null) - { - throw new ArgumentNullException("hashAlgorithm"); - } - - if (string.IsNullOrEmpty(data)) - { - throw new ArgumentNullException("data"); - } - - byte[] dataBuffer = System.Text.Encoding.ASCII.GetBytes(data); - byte[] hashBytes = hashAlgorithm.ComputeHash(dataBuffer); - - return Convert.ToBase64String(hashBytes); - } - - /// <summary> - /// Internal function to cut out all non oauth query string parameters (all parameters not begining with "oauth_") - /// </summary> - /// <param name="parameters">The query string part of the Url</param> - /// <returns>A list of QueryParameter each containing the parameter name and value</returns> - private List<QueryParameter> GetQueryParameters(string parameters) - { - if (parameters.StartsWith("?")) - { - parameters = parameters.Remove(0, 1); - } - - List<QueryParameter> result = new List<QueryParameter>(); - - if (!string.IsNullOrEmpty(parameters)) - { - string[] p = parameters.Split('&'); - foreach (string s in p) - { - if (!string.IsNullOrEmpty(s) && !s.StartsWith(OAuthParameterPrefix)) - { - if (s.IndexOf('=') > -1) - { - string[] temp = s.Split('='); - result.Add(new QueryParameter(temp[0], temp[1])); - } - else - { - result.Add(new QueryParameter(s, string.Empty)); - } - } - } - } - - return result; - } - - /// <summary> - /// This is a different Url Encode implementation since the default .NET one outputs the percent encoding in lower case. - /// While this is not a problem with the percent encoding spec, it is used in upper case throughout OAuth - /// </summary> - /// <param name="value">The value to Url encode</param> - /// <returns>Returns a Url encoded string</returns> - public string UrlEncode(string value) - { - StringBuilder result = new StringBuilder(); - - foreach (char symbol in value) - { - if (unreservedChars.IndexOf(symbol) != -1) - { - result.Append(symbol); - } - else - { - result.Append('%' + String.Format("{0:X2}", (int)symbol)); - } - } - - return result.ToString(); - } - - /// <summary> - /// Normalizes the request parameters according to the spec - /// </summary> - /// <param name="parameters">The list of parameters already sorted</param> - /// <returns>a string representing the normalized parameters</returns> - protected string NormalizeRequestParameters(IList<QueryParameter> parameters) - { - StringBuilder sb = new StringBuilder(); - QueryParameter p = null; - for (int i = 0; i < parameters.Count; i++) - { - p = parameters[i]; - sb.AppendFormat("{0}={1}", p.Name, p.Value); - - if (i < parameters.Count - 1) - { - sb.Append("&"); - } - } - - return sb.ToString(); - } - - /// <summary> - /// Generate the signature base that is used to produce the signature - /// </summary> - /// <param name="url">The full url that needs to be signed including its non OAuth url parameters</param> - /// <param name="consumerKey">The consumer key</param> - /// <param name="token">The token, if available. If not available pass null or an empty string</param> - /// <param name="tokenSecret">The token secret, if available. If not available pass null or an empty string</param> - /// <param name="callBackUrl">The callback URL (for OAuth 1.0a).If your client cannot accept callbacks, the value MUST be 'oob' </param> - /// <param name="oauthVerifier">This value MUST be included when exchanging Request Tokens for Access Tokens. Otherwise pass a null or an empty string</param> - /// <param name="httpMethod">The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)</param> - /// <param name="signatureType">The signature type. To use the default values use <see cref="OAuthBase.SignatureTypes">OAuthBase.SignatureTypes</see>.</param> - /// <returns>The signature base</returns> - public string GenerateSignatureBase(Uri url, string consumerKey, string token, string tokenSecret, string callBackUrl, string oauthVerifier, string httpMethod, string timeStamp, string nonce, string signatureType, out string normalizedUrl, out string normalizedRequestParameters) - { - if (token == null) - { - token = string.Empty; - } - - if (tokenSecret == null) - { - tokenSecret = string.Empty; - } - - if (string.IsNullOrEmpty(consumerKey)) - { - throw new ArgumentNullException("consumerKey"); - } - - if (string.IsNullOrEmpty(httpMethod)) - { - throw new ArgumentNullException("httpMethod"); - } - - if (string.IsNullOrEmpty(signatureType)) - { - throw new ArgumentNullException("signatureType"); - } - - normalizedUrl = null; - normalizedRequestParameters = null; - - List<QueryParameter> parameters = GetQueryParameters(url.Query); - parameters.Add(new QueryParameter(OAuthVersionKey, OAuthVersion)); - parameters.Add(new QueryParameter(OAuthNonceKey, nonce)); - parameters.Add(new QueryParameter(OAuthTimestampKey, timeStamp)); - parameters.Add(new QueryParameter(OAuthSignatureMethodKey, signatureType)); - parameters.Add(new QueryParameter(OAuthConsumerKeyKey, consumerKey)); - - if (!string.IsNullOrEmpty(callBackUrl)) - { - parameters.Add(new QueryParameter(OAuthCallbackKey, UrlEncode(callBackUrl))); - } - - - if (!string.IsNullOrEmpty(oauthVerifier)) - { - parameters.Add(new QueryParameter(OAuthVerifierKey, oauthVerifier)); - } - - if (!string.IsNullOrEmpty(token)) - { - parameters.Add(new QueryParameter(OAuthTokenKey, token)); - } - - parameters.Sort(new QueryParameterComparer()); - - normalizedUrl = string.Format("{0}://{1}", url.Scheme, url.Host); - if (!((url.Scheme == "http" && url.Port == 80) || (url.Scheme == "https" && url.Port == 443))) - { - normalizedUrl += ":" + url.Port; - } - normalizedUrl += url.AbsolutePath; - normalizedRequestParameters = NormalizeRequestParameters(parameters); - - StringBuilder signatureBase = new StringBuilder(); - signatureBase.AppendFormat("{0}&", httpMethod.ToUpper()); - signatureBase.AppendFormat("{0}&", UrlEncode(normalizedUrl)); - signatureBase.AppendFormat("{0}", UrlEncode(normalizedRequestParameters)); - - return signatureBase.ToString(); - } - - /// <summary> - /// Generate the signature value based on the given signature base and hash algorithm - /// </summary> - /// <param name="signatureBase">The signature based as produced by the GenerateSignatureBase method or by any other means</param> - /// <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> - /// <returns>A base64 string of the hash value</returns> - public string GenerateSignatureUsingHash(string signatureBase, HashAlgorithm hash) - { - return ComputeHash(hash, signatureBase); - } - - /// <summary> - /// Generates a signature using the HMAC-SHA1 algorithm - /// </summary> - /// <param name="url">The full url that needs to be signed including its non OAuth url parameters</param> - /// <param name="consumerKey">The consumer key</param> - /// <param name="consumerSecret">The consumer seceret</param> - /// <param name="token">The token, if available. If not available pass null or an empty string</param> - /// <param name="tokenSecret">The token secret, if available. If not available pass null or an empty string</param> - /// <param name="callBackUrl">The callback URL (for OAuth 1.0a).If your client cannot accept callbacks, the value MUST be 'oob' </param> - /// <param name="oauthVerifier">This value MUST be included when exchanging Request Tokens for Access Tokens. Otherwise pass a null or an empty string</param> - /// <param name="httpMethod">The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)</param> - /// <returns>A base64 string of the hash value</returns> - public string GenerateSignature(Uri url, string consumerKey, string consumerSecret, string token, string tokenSecret, string callBackUrl, string oauthVerifier, string httpMethod, string timeStamp, string nonce, out string normalizedUrl, out string normalizedRequestParameters) - { - return GenerateSignature(url, consumerKey, consumerSecret, token, tokenSecret, callBackUrl, oauthVerifier, httpMethod, timeStamp, nonce, SignatureTypes.HMACSHA1, out normalizedUrl, out normalizedRequestParameters); - } - - /// <summary> - /// Generates a signature using the specified signatureType - /// </summary> - /// <param name="url">The full url that needs to be signed including its non OAuth url parameters</param> - /// <param name="consumerKey">The consumer key</param> - /// <param name="consumerSecret">The consumer seceret</param> - /// <param name="token">The token, if available. If not available pass null or an empty string</param> - /// <param name="tokenSecret">The token secret, if available. If not available pass null or an empty string</param> - /// <param name="callBackUrl">The callback URL (for OAuth 1.0a).If your client cannot accept callbacks, the value MUST be 'oob' </param> - /// <param name="oauthVerifier">This value MUST be included when exchanging Request Tokens for Access Tokens. Otherwise pass a null or an empty string</param> - /// <param name="httpMethod">The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)</param> - /// <param name="signatureType">The type of signature to use</param> - /// <returns>A base64 string of the hash value</returns> - public string GenerateSignature(Uri url, string consumerKey, string consumerSecret, string token, string tokenSecret, string callBackUrl, string oauthVerifier, string httpMethod, string timeStamp, string nonce, SignatureTypes signatureType, out string normalizedUrl, out string normalizedRequestParameters) - { - normalizedUrl = null; - normalizedRequestParameters = null; - - switch (signatureType) - { - case SignatureTypes.PLAINTEXT: - return HttpUtility.UrlEncode(string.Format("{0}&{1}", consumerSecret, tokenSecret)); - case SignatureTypes.HMACSHA1: - string signatureBase = GenerateSignatureBase(url, consumerKey, token, tokenSecret, callBackUrl, oauthVerifier, httpMethod, timeStamp, nonce, HMACSHA1SignatureType, out normalizedUrl, out normalizedRequestParameters); - - HMACSHA1 hmacsha1 = new HMACSHA1(); - hmacsha1.Key = Encoding.ASCII.GetBytes(string.Format("{0}&{1}", UrlEncode(consumerSecret), string.IsNullOrEmpty(tokenSecret) ? "" : UrlEncode(tokenSecret))); - - return GenerateSignatureUsingHash(signatureBase, hmacsha1); - case SignatureTypes.RSASHA1: - throw new NotImplementedException(); - default: - throw new ArgumentException("Unknown signature type", "signatureType"); - } - } - - /// <summary> - /// Generate the timestamp for the signature - /// </summary> - /// <returns></returns> - public virtual string GenerateTimeStamp() - { - // Default implementation of UNIX time of the current UTC time - TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); - return Convert.ToInt64(ts.TotalSeconds).ToString(); - } - - /// <summary> - /// Generate a nonce - /// </summary> - /// <returns></returns> - public virtual string GenerateNonce() - { - // Just a simple implementation of a random number between 123400 and 9999999 - return random.Next(123400, 9999999).ToString(); - } - - } -} \ No newline at end of file
--- a/Agendas/trunk/src/Agendas.Twitter/oAuthTwitter.cs Mon Jun 06 14:07:12 2011 -0300 +++ b/Agendas/trunk/src/Agendas.Twitter/oAuthTwitter.cs Tue Jun 07 23:21:07 2011 -0300 @@ -1,257 +1,51 @@ -using System; +using System; using System.Configuration; -using System.Web; -using System.Net; -using System.IO; -using System.Collections.Specialized; +using Twitterizer; namespace AltNetHispano.Agendas.Twitter { - public class OAuthTwitter : OAuthBase - { - public enum Method { GET, POST, DELETE }; - public const string REQUEST_TOKEN = "http://twitter.com/oauth/request_token"; - public const string AUTHORIZE = "http://twitter.com/oauth/authorize"; - public const string ACCESS_TOKEN = "http://twitter.com/oauth/access_token"; - - private string _consumerKey = ""; - private string _consumerSecret = ""; - private string _token = ""; - private string _tokenSecret = ""; - private string _callBackUrl = "oob"; - private string _oauthVerifier = ""; - - private string ConsumerKey - { - get - { - if (_consumerKey.Length == 0) - { - _consumerKey = ConfigurationManager.AppSettings["consumerKey"]; - } - return _consumerKey; - } - } - - private string ConsumerSecret { - get { - if (_consumerSecret.Length == 0) - { - _consumerSecret = ConfigurationManager.AppSettings["consumerSecret"]; - } - return _consumerSecret; - } - } - - public string Token { get { return _token; } set { _token = value; } } - public string TokenSecret { get { return _tokenSecret; } set { _tokenSecret = value; } } - public string CallBackUrl { get { return _callBackUrl; } set { _callBackUrl = value; } } - public string OAuthVerifier { get { return _oauthVerifier; } set { _oauthVerifier = value; } } - - /// <summary> - /// Get the link to Twitter's authorization page for this application. - /// </summary> - /// <returns>The url with a valid request token, or a null string.</returns> - public string AuthorizationLinkGet() - { - string ret = null; - - string response = OAuthWebRequest(Method.GET, REQUEST_TOKEN, String.Empty); - if (response.Length > 0) - { - //response contains token and token secret. We only need the token. - NameValueCollection qs = HttpUtility.ParseQueryString(response); + public class OAuthTwitter + { + private string ConsumerKey + { + get { return ConfigurationManager.AppSettings["consumerKey"]; } + } - if (qs["oauth_callback_confirmed"] != null) - { - if (qs["oauth_callback_confirmed"] != "true") - { - throw new Exception("OAuth callback not confirmed."); - } - } - - if (qs[OAuthTokenKey] != null) - { - ret = AUTHORIZE + "?" + OAuthTokenKey + "=" + qs[OAuthTokenKey]; - } - } - return ret; - } - - /// <summary> - /// Exchange the request token for an access token. - /// </summary> - /// <param name="authToken">The oauth_token is supplied by Twitter's authorization page following the callback.</param> - /// <param name="oauthVerifier">An oauth_verifier parameter is provided to the client either in the pre-configured callback URL</param> - public void AccessTokenGet(string authToken, string oauthVerifier) - { - Token = authToken; - OAuthVerifier = oauthVerifier; - - string response = OAuthWebRequest(Method.GET, ACCESS_TOKEN, String.Empty); + private string ConsumerSecret + { + get { return ConfigurationManager.AppSettings["consumerSecret"]; } + } - if (response.Length > 0) - { - //Store the Token and Token Secret - NameValueCollection qs = HttpUtility.ParseQueryString(response); - if (qs[OAuthTokenKey] != null) - { - Token = qs[OAuthTokenKey]; - } - if (qs[OAuthTokenSecretKey] != null) - { - TokenSecret = qs[OAuthTokenSecretKey]; - } - } - } - - /// <summary> - /// Submit a web request using oAuth. - /// </summary> - /// <param name="method">GET or POST</param> - /// <param name="url">The full url, including the querystring.</param> - /// <param name="postData">Data to post (querystring format)</param> - /// <returns>The web server response.</returns> - public string OAuthWebRequest(Method method, string url, string postData) - { - string outUrl; - string querystring; - string ret; + public Uri AuthorizationLinkGet(string callbackAddress) + { + // Obtain a request token + OAuthTokenResponse requestToken = OAuthUtility.GetRequestToken(ConsumerKey, ConsumerSecret, callbackAddress); + // Direct or instruct the user to the following address: + Uri authorizationUri = OAuthUtility.BuildAuthorizationUri(requestToken.Token); + + return authorizationUri; + } - //Setup postData for signing. - //Add the postData to the querystring. - if (method == Method.POST || method == Method.DELETE) - { - if (postData.Length > 0) - { - //Decode the parameters and re-encode using the oAuth UrlEncode method. - NameValueCollection qs = HttpUtility.ParseQueryString(postData); - postData = ""; - foreach (string key in qs.AllKeys) - { - if (postData.Length > 0) - { - postData += "&"; - } - qs[key] = HttpUtility.UrlDecode(qs[key]); - qs[key] = UrlEncode(qs[key]); - postData += key + "=" + qs[key]; - - } - if (url.IndexOf("?") > 0) - { - url += "&"; - } - else - { - url += "?"; - } - url += postData; - } - } - - var uri = new Uri(url); - - string nonce = GenerateNonce(); - string timeStamp = GenerateTimeStamp(); - - //Generate Signature - string sig = GenerateSignature(uri, - ConsumerKey, - ConsumerSecret, - Token, - TokenSecret, - CallBackUrl, - OAuthVerifier, - method.ToString(), - timeStamp, - nonce, - out outUrl, - out querystring); - - querystring += "&" + OAuthSignatureKey + "=" + UrlEncode(sig); - - //Convert the querystring to postData - if (method == Method.POST || method == Method.DELETE) - { - postData = querystring; - querystring = ""; - } - - if (querystring.Length > 0) - { - outUrl += "?"; - } - - ret = WebRequest(method, outUrl + querystring, postData); + public string AccessTokenGet(string requestToken, string verifier) + { + OAuthTokenResponse accessToken = OAuthUtility.GetAccessToken(ConsumerKey, ConsumerSecret, requestToken, verifier); + if (accessToken!=null) + { + var tokens = new OAuthTokens + { + AccessToken = accessToken.Token, + AccessTokenSecret = accessToken.TokenSecret, + ConsumerKey = ConsumerKey, + ConsumerSecret = ConsumerSecret + }; - return ret; - } - - /// <summary> - /// Web Request Wrapper - /// </summary> - /// <param name="method">Http Method</param> - /// <param name="url">Full url to the web resource</param> - /// <param name="postData">Data to post in querystring format</param> - /// <returns>The web server response.</returns> - public string WebRequest(Method method, string url, string postData) - { - HttpWebRequest webRequest; - StreamWriter requestWriter; - string responseData; - - webRequest = System.Net.WebRequest.Create(url) as HttpWebRequest; - webRequest.Method = method.ToString(); - webRequest.ServicePoint.Expect100Continue = false; - //webRequest.UserAgent = "Identify your application please."; - //webRequest.Timeout = 20000; - - if (method == Method.POST || method == Method.DELETE) - { - webRequest.ContentType = "application/x-www-form-urlencoded"; - - //POST the data. - requestWriter = new StreamWriter(webRequest.GetRequestStream()); - try - { - requestWriter.Write(postData); - } - finally - { - requestWriter.Close(); - } - } - - responseData = WebResponseGet(webRequest); - - return responseData; - - } - - /// <summary> - /// Process the web response. - /// </summary> - /// <param name="webRequest">The request object.</param> - /// <returns>The response data.</returns> - public string WebResponseGet(HttpWebRequest webRequest) - { - StreamReader responseReader = null; - string responseData; - - try - { - responseReader = new StreamReader(webRequest.GetResponse().GetResponseStream()); - responseData = responseReader.ReadToEnd(); - } - finally - { - webRequest.GetResponse().GetResponseStream().Close(); - responseReader.Close(); - } - - return responseData; - } - } + TwitterResponse<TwitterUser> showUserResponse = TwitterUser.Show(tokens, accessToken.UserId); + if (showUserResponse.Result == RequestResult.Success) + return showUserResponse.Content; + return showUserResponse.ErrorMessage; + } + return string.Empty; + } + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Agendas/trunk/src/Agendas.Twitter/packages.config Tue Jun 07 23:21:07 2011 -0300 @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="Newtonsoft.Json" version="3.5.8" /> + <package id="twitterizer" version="2.3.2" /> +</packages> \ No newline at end of file
--- a/Agendas/trunk/src/Agendas.Web/Controllers/AccountController.cs Mon Jun 06 14:07:12 2011 -0300 +++ b/Agendas/trunk/src/Agendas.Web/Controllers/AccountController.cs Tue Jun 07 23:21:07 2011 -0300 @@ -62,27 +62,19 @@ if (Request["oauth_token"] == null) { - //Redirect the user to Twitter for authorization. - //Using oauth_callback for local testing. var action = Url.Action("TwitterLogOn"); var url = Request.Url.Scheme + "://" + Request.Url.Host + (Request.Url.Port != 80 ? ":" + Request.Url.Port : string.Empty) + action; - oAuth.CallBackUrl = url; - Response.Redirect(oAuth.AuthorizationLinkGet()); + Response.Redirect(oAuth.AuthorizationLinkGet(url).ToString()); } else { - //Get the access token and secret. - oAuth.AccessTokenGet(Request["oauth_token"], Request["oauth_verifier"]); - if (oAuth.TokenSecret.Length > 0) + var response = oAuth.AccessTokenGet(Request["oauth_token"], Request["oauth_verifier"]); + if (response.Length > 0) { - //We now have the credentials, so make a call to the Twitter API. - const string url = "http://twitter.com/account/verify_credentials.xml"; - string xml = oAuth.OAuthWebRequest(OAuthTwitter.Method.GET, url, String.Empty); - - var username = GetXmlContent(xml, "screen_name"); - var nombre = GetXmlContent(xml, "name"); + var username = GetResponseContent(response, "screen_name"); + var nombre = GetResponseContent(response, "name"); var personaService = AgendaFactory.GetPersonaService(); if (personaService.Validate(IdentityProviderEnum.Twitter, username, nombre)) @@ -91,34 +83,28 @@ return RedirectToAction("Index", "Home"); } ModelState.AddModelError("", "The user name or password provided is incorrect."); - - - //POST Test - //url = "http://twitter.com/statuses/update.xml"; - //xml = oAuth.oAuthWebRequest(oAuthTwitter.Method.POST, url, "status=" + oAuth.UrlEncode("Hello @swhitley - Testing the .NET oAuth API")); - //apiResponse.InnerHtml = Server.HtmlEncode(xml); } } return RedirectToAction("LogOn"); } - private static string GetXmlContent(string xml, string tagName) - { - var tagStart = "<" + tagName + ">"; - var tagEnd = "</" + tagName + ">"; + private static string GetResponseContent(string response, string tagName) + { + var tagStart = "\"" + tagName + "\":"; + var tagEnd = ","; - var start = xml.IndexOf(tagStart)+tagStart.Length; - if (start>tagStart.Length) + var start = response.IndexOf(tagStart) + tagStart.Length; + if (start > tagStart.Length) { - var end = xml.IndexOf(tagEnd, start); - if (end>0) + var end = response.IndexOf(tagEnd, start); + if (end > 0) { - return xml.Substring(start, end - start); + return response.Substring(start + 1, end - start - 2); } } - return string.Empty; - } + return string.Empty; + } // ************************************** // URL: /Account/LogOff
--- a/Agendas/trunk/src/Agendas.sln Mon Jun 06 14:07:12 2011 -0300 +++ b/Agendas/trunk/src/Agendas.sln Tue Jun 07 23:21:07 2011 -0300 @@ -30,6 +30,8 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Agendas.Resources", "Agendas.Resources\Agendas.Resources.csproj", "{444D25FB-FC1C-48DC-9EAD-D4C78F2A10CA}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Agendas.Twitter.Tests", "Agendas.Twitter.Tests\Agendas.Twitter.Tests.csproj", "{462D86DD-7F4D-4596-B18B-2DD92C7FD73F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -80,6 +82,10 @@ {444D25FB-FC1C-48DC-9EAD-D4C78F2A10CA}.Debug|Any CPU.Build.0 = Debug|Any CPU {444D25FB-FC1C-48DC-9EAD-D4C78F2A10CA}.Release|Any CPU.ActiveCfg = Release|Any CPU {444D25FB-FC1C-48DC-9EAD-D4C78F2A10CA}.Release|Any CPU.Build.0 = Release|Any CPU + {462D86DD-7F4D-4596-B18B-2DD92C7FD73F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {462D86DD-7F4D-4596-B18B-2DD92C7FD73F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {462D86DD-7F4D-4596-B18B-2DD92C7FD73F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {462D86DD-7F4D-4596-B18B-2DD92C7FD73F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE
--- a/Agendas/trunk/src/install packages.bat Mon Jun 06 14:07:12 2011 -0300 +++ b/Agendas/trunk/src/install packages.bat Tue Jun 07 23:21:07 2011 -0300 @@ -2,5 +2,7 @@ ..\tools\nuget i Agendas.Repositories.NHibernate\packages.config -o packages ..\tools\nuget i Agendas.NHibernate\packages.config -o packages ..\tools\nuget i Agendas.Web\packages.config -o packages +..\tools\nuget i Agendas.Twitter\packages.config -o packages +..\tools\nuget i Agendas.Twitter.Tests\packages.config -o packages PAUSE \ No newline at end of file