Statistics
| Branch: | Revision:

root / trunk / Pithos.Client.WPF / PithosAccount.cs @ 7a804364

History | View | Annotate | Download (11.2 kB)

1 255f5f86 Panagiotis Kanavos
#region
2 255f5f86 Panagiotis Kanavos
/* -----------------------------------------------------------------------
3 255f5f86 Panagiotis Kanavos
 * <copyright file="PithosAccount.cs" company="GRNet">
4 255f5f86 Panagiotis Kanavos
 * 
5 255f5f86 Panagiotis Kanavos
 * Copyright 2011-2012 GRNET S.A. All rights reserved.
6 255f5f86 Panagiotis Kanavos
 *
7 255f5f86 Panagiotis Kanavos
 * Redistribution and use in source and binary forms, with or
8 255f5f86 Panagiotis Kanavos
 * without modification, are permitted provided that the following
9 255f5f86 Panagiotis Kanavos
 * conditions are met:
10 255f5f86 Panagiotis Kanavos
 *
11 255f5f86 Panagiotis Kanavos
 *   1. Redistributions of source code must retain the above
12 255f5f86 Panagiotis Kanavos
 *      copyright notice, this list of conditions and the following
13 255f5f86 Panagiotis Kanavos
 *      disclaimer.
14 255f5f86 Panagiotis Kanavos
 *
15 255f5f86 Panagiotis Kanavos
 *   2. Redistributions in binary form must reproduce the above
16 255f5f86 Panagiotis Kanavos
 *      copyright notice, this list of conditions and the following
17 255f5f86 Panagiotis Kanavos
 *      disclaimer in the documentation and/or other materials
18 255f5f86 Panagiotis Kanavos
 *      provided with the distribution.
19 255f5f86 Panagiotis Kanavos
 *
20 255f5f86 Panagiotis Kanavos
 *
21 255f5f86 Panagiotis Kanavos
 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
22 255f5f86 Panagiotis Kanavos
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 255f5f86 Panagiotis Kanavos
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 255f5f86 Panagiotis Kanavos
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
25 255f5f86 Panagiotis Kanavos
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 255f5f86 Panagiotis Kanavos
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 255f5f86 Panagiotis Kanavos
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28 255f5f86 Panagiotis Kanavos
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 255f5f86 Panagiotis Kanavos
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 255f5f86 Panagiotis Kanavos
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 255f5f86 Panagiotis Kanavos
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 255f5f86 Panagiotis Kanavos
 * POSSIBILITY OF SUCH DAMAGE.
33 255f5f86 Panagiotis Kanavos
 *
34 255f5f86 Panagiotis Kanavos
 * The views and conclusions contained in the software and
35 255f5f86 Panagiotis Kanavos
 * documentation are those of the authors and should not be
36 255f5f86 Panagiotis Kanavos
 * interpreted as representing official policies, either expressed
37 255f5f86 Panagiotis Kanavos
 * or implied, of GRNET S.A.
38 255f5f86 Panagiotis Kanavos
 * </copyright>
39 255f5f86 Panagiotis Kanavos
 * -----------------------------------------------------------------------
40 255f5f86 Panagiotis Kanavos
 */
41 255f5f86 Panagiotis Kanavos
#endregion
42 f3d080df Panagiotis Kanavos
43 1955901a Panagiotis Kanavos
// </copyright>
44 1955901a Panagiotis Kanavos
// -----------------------------------------------------------------------
45 1955901a Panagiotis Kanavos
46 03ee454f Panagiotis Kanavos
using System.IO;
47 db8a9589 Panagiotis Kanavos
using System.Reflection;
48 badcef63 Panagiotis Kanavos
using Pithos.Client.WPF.Preferences;
49 dd19241a pkanavos
using Pithos.Client.WPF.Properties;
50 5120f3cb Panagiotis Kanavos
using Pithos.Network;
51 5120f3cb Panagiotis Kanavos
using log4net;
52 5120f3cb Panagiotis Kanavos
53 1955901a Panagiotis Kanavos
namespace Pithos.Client.WPF
54 1955901a Panagiotis Kanavos
{
55 1955901a Panagiotis Kanavos
    using System;
56 1955901a Panagiotis Kanavos
    using System.Collections.Generic;
57 1955901a Panagiotis Kanavos
    using System.Linq;
58 1955901a Panagiotis Kanavos
    using System.Text;
59 1955901a Panagiotis Kanavos
    using System.Net;
60 1955901a Panagiotis Kanavos
    using System.Threading.Tasks;
61 1955901a Panagiotis Kanavos
    using System.Diagnostics.Contracts;
62 1955901a Panagiotis Kanavos
    using System.Diagnostics;
63 1955901a Panagiotis Kanavos
    using System.Net.Sockets;
64 1955901a Panagiotis Kanavos
65 1955901a Panagiotis Kanavos
    /// <summary>
66 1955901a Panagiotis Kanavos
    /// TODO: Update summary.
67 1955901a Panagiotis Kanavos
    /// </summary>
68 1955901a Panagiotis Kanavos
    /// <summary>
69 1955901a Panagiotis Kanavos
    /// Retrieves an account name and token from PITHOS
70 1955901a Panagiotis Kanavos
    /// </summary>
71 1955901a Panagiotis Kanavos
    public static class PithosAccount
72 1955901a Panagiotis Kanavos
    {
73 db8a9589 Panagiotis Kanavos
        private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
74 5120f3cb Panagiotis Kanavos
75 1955901a Panagiotis Kanavos
        /// <summary>
76 1955901a Panagiotis Kanavos
        /// Asynchronously retrieves PITHOS credentials
77 1955901a Panagiotis Kanavos
        /// </summary>
78 20e9a378 Panagiotis Kanavos
        /// <param name="loginUrl">URL to retrieve the account info from PITHOS. Must end with =</param>
79 1955901a Panagiotis Kanavos
        /// <returns>The credentials wrapped in a Task</returns>
80 badcef63 Panagiotis Kanavos
        public static NetworkCredential RetrieveCredentials(string loginUrl,string accountName=null)
81 1955901a Panagiotis Kanavos
        {
82 20e9a378 Panagiotis Kanavos
            Contract.Requires(Uri.IsWellFormedUriString(loginUrl, UriKind.Absolute));
83 1955901a Panagiotis Kanavos
84 20e9a378 Panagiotis Kanavos
            if (!Uri.IsWellFormedUriString(loginUrl, UriKind.Absolute))
85 20e9a378 Panagiotis Kanavos
                throw new ArgumentException("The pithosSite parameter must be a valid absolute URL", "loginUrl");
86 1955901a Panagiotis Kanavos
            
87 badcef63 Panagiotis Kanavos
            //int port = GetFreePort();
88 28076364 Panagiotis Kanavos
            
89 28076364 Panagiotis Kanavos
            //TODO:Force logout here to take care of existing cookies
90 1955901a Panagiotis Kanavos
91 1955901a Panagiotis Kanavos
92 badcef63 Panagiotis Kanavos
            //var listenerUrl = String.Format("http://127.0.0.1:{0}", port);
93 badcef63 Panagiotis Kanavos
            var listenerUrl = "pithos://127.0.0.1";
94 1955901a Panagiotis Kanavos
95 03ee454f Panagiotis Kanavos
            
96 1955901a Panagiotis Kanavos
97 badcef63 Panagiotis Kanavos
            //var receiveCredentials = ListenForRedirectAsync(port);
98 03ee454f Panagiotis Kanavos
99 badcef63 Panagiotis Kanavos
            //var logoutUrl = loginUrl.Replace("login", "im/logout");
100 badcef63 Panagiotis Kanavos
            //var logoutProcess=Process.Start(logoutUrl);            
101 badcef63 Panagiotis Kanavos
            //TaskEx.Delay(2000).Wait();
102 badcef63 Panagiotis Kanavos
            var uriBuilder = new UriBuilder(loginUrl)
103 badcef63 Panagiotis Kanavos
                                 {
104 badcef63 Panagiotis Kanavos
                                     Query = String.Format("next={0}&force=", listenerUrl)
105 badcef63 Panagiotis Kanavos
                                 };
106 03ee454f Panagiotis Kanavos
107 03ee454f Panagiotis Kanavos
            var retrieveUri = uriBuilder.Uri;
108 badcef63 Panagiotis Kanavos
109 dd19241a pkanavos
            var logoutUrl= (from server in Settings.Default.Servers
110 dd19241a pkanavos
                           where server.LoginUri == loginUrl
111 dd19241a pkanavos
                               select new Uri(server.LogoutUri)).FirstOrDefault();
112 badcef63 Panagiotis Kanavos
113 dd19241a pkanavos
114 dd19241a pkanavos
115 dd19241a pkanavos
            var browser = new LoginView(retrieveUri,logoutUrl,accountName);            
116 badcef63 Panagiotis Kanavos
            if (true == browser.ShowDialog())
117 badcef63 Panagiotis Kanavos
            {
118 badcef63 Panagiotis Kanavos
                return new NetworkCredential(browser.Account, browser.Token);
119 badcef63 Panagiotis Kanavos
            }
120 badcef63 Panagiotis Kanavos
            return null;
121 badcef63 Panagiotis Kanavos
122 badcef63 Panagiotis Kanavos
/*
123 badcef63 Panagiotis Kanavos
124 03ee454f Panagiotis Kanavos
            Log.InfoFormat("[RETRIEVE] Open Browser at {0}", retrieveUri);
125 03ee454f Panagiotis Kanavos
            Process.Start(retrieveUri.ToString());
126 03ee454f Panagiotis Kanavos
127 03ee454f Panagiotis Kanavos
            return receiveCredentials;
128 badcef63 Panagiotis Kanavos
*/
129 03ee454f Panagiotis Kanavos
        }
130 03ee454f Panagiotis Kanavos
131 34bdb91d Panagiotis Kanavos
/*
132 03ee454f Panagiotis Kanavos
        private static async Task<NetworkCredential> ListenHttpForRedirectAsync(string listenerUrl)
133 03ee454f Panagiotis Kanavos
        {
134 03ee454f Panagiotis Kanavos
            using (var listener = new HttpListener())
135 03ee454f Panagiotis Kanavos
            {
136 03ee454f Panagiotis Kanavos
                listener.Prefixes.Add(listenerUrl);
137 03ee454f Panagiotis Kanavos
138 03ee454f Panagiotis Kanavos
                Log.InfoFormat("[RETRIEVE] Listening at {0}", listenerUrl);
139 1955901a Panagiotis Kanavos
140 1955901a Panagiotis Kanavos
141 03ee454f Panagiotis Kanavos
                try
142 1955901a Panagiotis Kanavos
                {
143 03ee454f Panagiotis Kanavos
                    listener.Start();
144 1955901a Panagiotis Kanavos
145 03ee454f Panagiotis Kanavos
                    var context = await listener.GetContextAsync()
146 03ee454f Panagiotis Kanavos
                                            .WithTimeout(TimeSpan.FromMinutes(5));
147 1955901a Panagiotis Kanavos
148 03ee454f Panagiotis Kanavos
                    var request = context.Request;
149 03ee454f Panagiotis Kanavos
                    Log.InfoFormat("[RETRIEVE] Got Connection {0}", request.RawUrl);
150 03ee454f Panagiotis Kanavos
151 03ee454f Panagiotis Kanavos
                    var query = request.QueryString;
152 03ee454f Panagiotis Kanavos
                    var userName = query["user"];
153 03ee454f Panagiotis Kanavos
                    var token = query["token"];
154 03ee454f Panagiotis Kanavos
                    if (String.IsNullOrWhiteSpace(userName) ||
155 03ee454f Panagiotis Kanavos
                        String.IsNullOrWhiteSpace(token))
156 03ee454f Panagiotis Kanavos
                    {
157 03ee454f Panagiotis Kanavos
                        Respond(context, "Failure", "The server did not return a username or token");
158 03ee454f Panagiotis Kanavos
                        Log.ErrorFormat("[RETRIEVE] No credentials returned by server");
159 03ee454f Panagiotis Kanavos
                        throw new Exception("The server did not return a username or token");
160 1955901a Panagiotis Kanavos
                    }
161 03ee454f Panagiotis Kanavos
                    else
162 1955901a Panagiotis Kanavos
                    {
163 03ee454f Panagiotis Kanavos
                        Log.InfoFormat("[RETRIEVE] Credentials retrieved user:{0} token:{1}", userName, token);
164 03ee454f Panagiotis Kanavos
                        Respond(context, "Authenticated", "Got It");
165 03ee454f Panagiotis Kanavos
166 03ee454f Panagiotis Kanavos
                        return new NetworkCredential(userName, token);
167 1955901a Panagiotis Kanavos
                    }
168 03ee454f Panagiotis Kanavos
                }
169 03ee454f Panagiotis Kanavos
                catch (Exception exc)
170 03ee454f Panagiotis Kanavos
                {
171 03ee454f Panagiotis Kanavos
                    Log.Error("[RETRIEVE][ERROR] Receive connection {0}", exc);
172 03ee454f Panagiotis Kanavos
                    throw;
173 03ee454f Panagiotis Kanavos
                }
174 03ee454f Panagiotis Kanavos
            }
175 03ee454f Panagiotis Kanavos
        }
176 34bdb91d Panagiotis Kanavos
*/
177 1955901a Panagiotis Kanavos
178 03ee454f Panagiotis Kanavos
        private static async Task<NetworkCredential> ListenForRedirectAsync(int port)
179 03ee454f Panagiotis Kanavos
        {
180 03ee454f Panagiotis Kanavos
            var listener = new TcpListener(IPAddress.Any, port);            
181 03ee454f Panagiotis Kanavos
            Log.InfoFormat("[RETRIEVE] Listening at {0}", port);
182 1955901a Panagiotis Kanavos
183 03ee454f Panagiotis Kanavos
            try
184 03ee454f Panagiotis Kanavos
            {
185 03ee454f Panagiotis Kanavos
                listener.Start();
186 1955901a Panagiotis Kanavos
187 03ee454f Panagiotis Kanavos
                using (var client = await listener.AcceptTcpClientAsync()
188 03ee454f Panagiotis Kanavos
                                        .WithTimeout(TimeSpan.FromMinutes(5)))
189 03ee454f Panagiotis Kanavos
                {
190 03ee454f Panagiotis Kanavos
                    using (var stream = client.GetStream())
191 03ee454f Panagiotis Kanavos
                    using (var reader=new StreamReader(stream))
192 03ee454f Panagiotis Kanavos
                    {
193 03ee454f Panagiotis Kanavos
                        var request = await reader.ReadLineAsync();
194 1a3dfbfd Panagiotis Kanavos
                        //BUG
195 1a3dfbfd Panagiotis Kanavos
                        //TODO: Add proper warnings here if the content is empty, don't just throw an exception
196 1a3dfbfd Panagiotis Kanavos
                        //This may be a common occurence 
197 1a3dfbfd Panagiotis Kanavos
198 1a3dfbfd Panagiotis Kanavos
                        if (String.IsNullOrWhiteSpace(request))
199 34bdb91d Panagiotis Kanavos
                            throw new PithosException("The server did send any information");
200 03ee454f Panagiotis Kanavos
                        Log.InfoFormat("[RETRIEVE] Got Connection {0}", request);
201 03ee454f Panagiotis Kanavos
202 03ee454f Panagiotis Kanavos
203 28076364 Panagiotis Kanavos
                        var items = ParseResponse(request);
204 03ee454f Panagiotis Kanavos
205 03ee454f Panagiotis Kanavos
                        var userName = items["user"];
206 03ee454f Panagiotis Kanavos
                        var token = items["token"];
207 03ee454f Panagiotis Kanavos
                        if (String.IsNullOrWhiteSpace(userName) ||
208 03ee454f Panagiotis Kanavos
                            String.IsNullOrWhiteSpace(token))
209 03ee454f Panagiotis Kanavos
                        {
210 03ee454f Panagiotis Kanavos
                            Respond(stream, "Failure", "The server did not return a username or token");
211 03ee454f Panagiotis Kanavos
                            Log.ErrorFormat("[RETRIEVE] No credentials returned by server");
212 34bdb91d Panagiotis Kanavos
                            throw new PithosException("The server did not return a username or token");
213 03ee454f Panagiotis Kanavos
                        }
214 03ee454f Panagiotis Kanavos
                        else
215 03ee454f Panagiotis Kanavos
                        {
216 03ee454f Panagiotis Kanavos
                            Log.InfoFormat("[RETRIEVE] Credentials retrieved user:{0} token:{1}", userName, token);
217 03ee454f Panagiotis Kanavos
                            Respond(stream, "Authenticated", "Got It");                            
218 03ee454f Panagiotis Kanavos
                        }
219 03ee454f Panagiotis Kanavos
                        return new NetworkCredential(userName, token);
220 03ee454f Panagiotis Kanavos
                    }
221 03ee454f Panagiotis Kanavos
                }
222 03ee454f Panagiotis Kanavos
            }
223 03ee454f Panagiotis Kanavos
            catch (Exception exc)
224 03ee454f Panagiotis Kanavos
            {
225 03ee454f Panagiotis Kanavos
                Log.Error("[RETRIEVE][ERROR] Receive connection {0}", exc);
226 34bdb91d Panagiotis Kanavos
                throw new PithosException("An error occured while retrieving credentials",exc);
227 03ee454f Panagiotis Kanavos
            }
228 1955901a Panagiotis Kanavos
        }
229 1955901a Panagiotis Kanavos
230 28076364 Panagiotis Kanavos
        private static Dictionary<string, string> ParseResponse(string request)
231 28076364 Panagiotis Kanavos
        {
232 28076364 Panagiotis Kanavos
            var parts = request.Split(' ');
233 28076364 Panagiotis Kanavos
            var query = parts[1].TrimStart('/', '?');
234 28076364 Panagiotis Kanavos
235 28076364 Panagiotis Kanavos
            var items = query.Split('&')
236 28076364 Panagiotis Kanavos
                .Select(pair => pair.Split('='))
237 28076364 Panagiotis Kanavos
                .ToDictionary(arr => arr[0].ToLower(), arr => Uri.UnescapeDataString(arr[1]));
238 28076364 Panagiotis Kanavos
            return items;
239 28076364 Panagiotis Kanavos
        }
240 03ee454f Panagiotis Kanavos
241 03ee454f Panagiotis Kanavos
242 437abfca Panagiotis Kanavos
        private static void Respond(HttpListenerContext context,string title,string message)
243 1955901a Panagiotis Kanavos
        {
244 1955901a Panagiotis Kanavos
            var response = context.Response;
245 437abfca Panagiotis Kanavos
            var html = String.Format("<html><head><title>{0}</title></head><body><h1>{1}</h1></body></html>", title, message);
246 437abfca Panagiotis Kanavos
            var outBuffer = Encoding.UTF8.GetBytes(html);
247 1955901a Panagiotis Kanavos
            response.ContentLength64 = outBuffer.Length;
248 1955901a Panagiotis Kanavos
            using (var stream = response.OutputStream)
249 1955901a Panagiotis Kanavos
            {
250 1955901a Panagiotis Kanavos
                stream.Write(outBuffer, 0, outBuffer.Length);
251 1955901a Panagiotis Kanavos
            }
252 1955901a Panagiotis Kanavos
253 5120f3cb Panagiotis Kanavos
            Log.InfoFormat("[RETRIEVE] Responded");
254 1955901a Panagiotis Kanavos
        }
255 03ee454f Panagiotis Kanavos
256 03ee454f Panagiotis Kanavos
        private static void Respond(Stream stream,string title,string message)
257 03ee454f Panagiotis Kanavos
        {
258 03ee454f Panagiotis Kanavos
            
259 03ee454f Panagiotis Kanavos
            var html = String.Format("<html><head><title>{0}</title></head><body><h1>{1}</h1></body></html>", title, message);
260 03ee454f Panagiotis Kanavos
            
261 03ee454f Panagiotis Kanavos
            var response = new StringBuilder();
262 03ee454f Panagiotis Kanavos
            response.AppendLine("HTTP/1.1 200 OK");
263 03ee454f Panagiotis Kanavos
            response.AppendFormat("Content-Length: {0}\n", html.Length);
264 03ee454f Panagiotis Kanavos
            response.AppendLine("Server: Microsoft-HTTPAPI/2.0");
265 03ee454f Panagiotis Kanavos
            response.AppendFormat("Date: {0}\n\n", DateTime.UtcNow);
266 03ee454f Panagiotis Kanavos
            response.AppendLine(html);
267 03ee454f Panagiotis Kanavos
268 03ee454f Panagiotis Kanavos
            var outBuffer=Encoding.UTF8.GetBytes(response.ToString());
269 03ee454f Panagiotis Kanavos
            
270 03ee454f Panagiotis Kanavos
            stream.Write(outBuffer, 0, outBuffer.Length);
271 03ee454f Panagiotis Kanavos
272 03ee454f Panagiotis Kanavos
            Log.InfoFormat("[RETRIEVE] Responded");
273 03ee454f Panagiotis Kanavos
        }
274 03ee454f Panagiotis Kanavos
275 03ee454f Panagiotis Kanavos
       
276 1955901a Panagiotis Kanavos
        /// <summary>
277 1955901a Panagiotis Kanavos
        /// Locates a free local port 
278 1955901a Panagiotis Kanavos
        /// </summary>
279 1955901a Panagiotis Kanavos
        /// <returns>A free port</returns>
280 1955901a Panagiotis Kanavos
        /// <remarks>The method starts and stops a TcpListener on port 0 to locate a free port.</remarks>
281 1955901a Panagiotis Kanavos
        public static int GetFreePort()
282 1955901a Panagiotis Kanavos
        {
283 1955901a Panagiotis Kanavos
            //The TcpListener will locate a free port             
284 1955901a Panagiotis Kanavos
            var listener = new TcpListener(IPAddress.Any, 0);
285 1955901a Panagiotis Kanavos
            listener.Start();
286 1955901a Panagiotis Kanavos
            var port = ((IPEndPoint)listener.LocalEndpoint).Port;
287 1955901a Panagiotis Kanavos
            listener.Stop();
288 1955901a Panagiotis Kanavos
            return port;
289 1955901a Panagiotis Kanavos
        }
290 1955901a Panagiotis Kanavos
    }
291 1955901a Panagiotis Kanavos
}