Browse code

Merge branch 'pr/12'

Pierre-David BeĢlanger authored on 13/07/2015 15:31:19
Showing 9 changed files
... ...
@@ -1,5 +1,4 @@
1 1
 using System.Reflection;
2
-using System.Runtime.CompilerServices;
3 2
 
4 3
 /*
5 4
     ChatterBotAPI
... ...
@@ -27,5 +26,4 @@ using System.Runtime.CompilerServices;
27 26
 [assembly: AssemblyCopyright("pierredavidbelanger")]
28 27
 [assembly: AssemblyTrademark("")]
29 28
 [assembly: AssemblyCulture("")]
30
-
31 29
 [assembly: AssemblyVersion("1.1.*")]
32 30
\ No newline at end of file
... ...
@@ -1,6 +1,4 @@
1
-using System;
2
-
3
-/*
1
+ /*
4 2
     ChatterBotAPI
5 3
     Copyright (C) 2011 pierredavidbelanger@gmail.com
6 4
  
... ...
@@ -17,10 +15,11 @@ using System;
17 15
     You should have received a copy of the GNU Lesser General Public License
18 16
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 17
 */
20
-namespace ChatterBotAPI {
21
-	
22
-	public interface ChatterBot {
23
-		
24
-		ChatterBotSession CreateSession();
25
-	}
18
+
19
+namespace ChatterBotAPI
20
+{
21
+    public interface ChatterBot
22
+    {
23
+        ChatterBotSession CreateSession();
24
+    }
26 25
 }
27 26
\ No newline at end of file
... ...
@@ -17,25 +17,29 @@ using System;
17 17
     You should have received a copy of the GNU Lesser General Public License
18 18
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 19
 */
20
-namespace ChatterBotAPI {
21
-	
22
-	public class ChatterBotFactory {
23
-		
24
-		public ChatterBot Create(ChatterBotType type) {
25
-			return Create(type, null);
26
-		}
27 20
 
28
-		public ChatterBot Create(ChatterBotType type, object arg) {
29
-			switch (type) {
30
-			case ChatterBotType.CLEVERBOT:
31
-				return new Cleverbot("http://www.cleverbot.com/webservicemin", 26);
32
-			case ChatterBotType.JABBERWACKY:
33
-				return new Cleverbot("http://jabberwacky.com/webservicemin", 20);
34
-			case ChatterBotType.PANDORABOTS:
35
-				if (arg == null) throw new ApplicationException("PANDORABOTS needs a botid arg");
36
-				return new Pandorabots(arg.ToString());
37
-			}
38
-			return null;
39
-		}
40
-	}
21
+namespace ChatterBotAPI
22
+{
23
+    public class ChatterBotFactory
24
+    {
25
+        public ChatterBot Create(ChatterBotType type)
26
+        {
27
+            return Create(type, null);
28
+        }
29
+
30
+        public ChatterBot Create(ChatterBotType type, object arg)
31
+        {
32
+            switch (type)
33
+            {
34
+                case ChatterBotType.CLEVERBOT:
35
+                    return new Cleverbot("http://www.cleverbot.com/", "http://www.cleverbot.com/webservicemin", 26);
36
+                case ChatterBotType.JABBERWACKY:
37
+                    return new Cleverbot("http://jabberwacky.com", "http://jabberwacky.com/webservicemin", 20);
38
+                case ChatterBotType.PANDORABOTS:
39
+                    if (arg == null) throw new ApplicationException("PANDORABOTS needs a botid arg");
40
+                    return new Pandorabots(arg.ToString());
41
+            }
42
+            return null;
43
+        }
44
+    }
41 45
 }
42 46
\ No newline at end of file
... ...
@@ -1,6 +1,4 @@
1
-using System;
2
-
3
-/*
1
+ /*
4 2
     ChatterBotAPI
5 3
     Copyright (C) 2011 pierredavidbelanger@gmail.com
6 4
  
... ...
@@ -17,12 +15,12 @@ using System;
17 15
     You should have received a copy of the GNU Lesser General Public License
18 16
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 17
 */
20
-namespace ChatterBotAPI {
21
-	
22
-	public interface ChatterBotSession {
23
-		
24
-		ChatterBotThought Think(ChatterBotThought thought);
25
-		
26
-		string Think(string text);
27
-	}
18
+
19
+namespace ChatterBotAPI
20
+{
21
+    public interface ChatterBotSession
22
+    {
23
+        ChatterBotThought Think(ChatterBotThought thought);
24
+        string Think(string text);
25
+    }
28 26
 }
29 27
\ No newline at end of file
... ...
@@ -1,6 +1,4 @@
1
-using System;
2
-
3
-/*
1
+ /*
4 2
     ChatterBotAPI
5 3
     Copyright (C) 2011 pierredavidbelanger@gmail.com
6 4
  
... ...
@@ -17,12 +15,12 @@ using System;
17 15
     You should have received a copy of the GNU Lesser General Public License
18 16
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 17
 */
20
-namespace ChatterBotAPI {
21
-	
22
-	public class ChatterBotThought {
23
-		
24
-		public string[] Emotions { get; set; }
25
-		
26
-		public string Text { get; set; }
27
-	}
18
+
19
+namespace ChatterBotAPI
20
+{
21
+    public class ChatterBotThought
22
+    {
23
+        public string[] Emotions { get; set; }
24
+        public string Text { get; set; }
25
+    }
28 26
 }
29 27
\ No newline at end of file
... ...
@@ -1,6 +1,4 @@
1
-using System;
2
-
3
-/*
1
+ /*
4 2
     ChatterBotAPI
5 3
     Copyright (C) 2011 pierredavidbelanger@gmail.com
6 4
  
... ...
@@ -17,11 +15,13 @@ using System;
17 15
     You should have received a copy of the GNU Lesser General Public License
18 16
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 17
 */
20
-namespace ChatterBotAPI {
21
-	
22
-	public enum ChatterBotType {
23
-		CLEVERBOT,
24
-		JABBERWACKY,
25
-		PANDORABOTS
26
-	}
18
+
19
+namespace ChatterBotAPI
20
+{
21
+    public enum ChatterBotType
22
+    {
23
+        CLEVERBOT,
24
+        JABBERWACKY,
25
+        PANDORABOTS
26
+    }
27 27
 }
28 28
\ No newline at end of file
... ...
@@ -1,6 +1,5 @@
1
-using System;
2
-
3 1
 using System.Collections.Generic;
2
+using System.Net;
4 3
 
5 4
 /*
6 5
     ChatterBotAPI
... ...
@@ -19,85 +18,99 @@ using System.Collections.Generic;
19 18
     You should have received a copy of the GNU Lesser General Public License
20 19
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 20
 */
22
-namespace ChatterBotAPI {
23
-	
24
-	class Cleverbot: ChatterBot {
25
-		private readonly string url;
26
-		private readonly int endIndex;
27
-		
28
-		public Cleverbot(string url, int endIndex) {
29
-			this.url = url;
30
-			this.endIndex = endIndex;
31
-		}
32
-		
33
-		public ChatterBotSession CreateSession() {
34
-			return new CleverbotSession(url, endIndex);
35
-		}
36
-	}
37
-	
38
-	class CleverbotSession: ChatterBotSession {
39
-		private readonly string url;
40
-		private readonly int endIndex;
41
-		private readonly IDictionary<string, string> vars;
42
-		
43
-		public CleverbotSession(string url, int endIndex) {
44
-			this.url = url;
45
-			this.endIndex = endIndex;
46
-			vars = new Dictionary<string, string>();
47
-			vars["start"] = "y";
48
-			vars["icognoid"] = "wsf";
49
-			vars["fno"] = "0";
50
-			vars["sub"] = "Say";
51
-			vars["islearning"] = "1";
52
-			vars["cleanslate"] = "false";
53
-		}
54
-		
55
-		public ChatterBotThought Think(ChatterBotThought thought) {
56
-			vars["stimulus"] = thought.Text;
57
-			
58
-			string formData = Utils.ParametersToWWWFormURLEncoded(vars);
59
-			string formDataToDigest = formData.Substring(9, endIndex);
60
-			string formDataDigest = Utils.MD5(formDataToDigest);
61
-			vars["icognocheck"] = formDataDigest;
62
-			
63
-			string response = Utils.Post(url, vars);
64
-			
65
-			string[] responseValues = response.Split('\r');
66
-			
67
-			//vars[""] = Utils.StringAtIndex(responseValues, 0); ??
68
-			vars["sessionid"] = Utils.StringAtIndex(responseValues, 1);
69
-			vars["logurl"] = Utils.StringAtIndex(responseValues, 2);
70
-			vars["vText8"] = Utils.StringAtIndex(responseValues, 3);
71
-			vars["vText7"] = Utils.StringAtIndex(responseValues, 4);
72
-			vars["vText6"] = Utils.StringAtIndex(responseValues, 5);
73
-			vars["vText5"] = Utils.StringAtIndex(responseValues, 6);
74
-			vars["vText4"] = Utils.StringAtIndex(responseValues, 7);
75
-			vars["vText3"] = Utils.StringAtIndex(responseValues, 8);
76
-			vars["vText2"] = Utils.StringAtIndex(responseValues, 9);
77
-			vars["prevref"] = Utils.StringAtIndex(responseValues, 10);
78
-			//vars[""] = Utils.StringAtIndex(responseValues, 11); ??
79
-			vars["emotionalhistory"] = Utils.StringAtIndex(responseValues, 12);
80
-			vars["ttsLocMP3"] = Utils.StringAtIndex(responseValues, 13);
81
-			vars["ttsLocTXT"] = Utils.StringAtIndex(responseValues, 14);
82
-			vars["ttsLocTXT3"] = Utils.StringAtIndex(responseValues, 15);
83
-			vars["ttsText"] = Utils.StringAtIndex(responseValues, 16);
84
-			vars["lineRef"] = Utils.StringAtIndex(responseValues, 17);
85
-			vars["lineURL"] = Utils.StringAtIndex(responseValues, 18);
86
-			vars["linePOST"] = Utils.StringAtIndex(responseValues, 19);
87
-			vars["lineChoices"] = Utils.StringAtIndex(responseValues, 20);
88
-			vars["lineChoicesAbbrev"] = Utils.StringAtIndex(responseValues, 21);
89
-			vars["typingData"] = Utils.StringAtIndex(responseValues, 22);
90
-			vars["divert"] = Utils.StringAtIndex(responseValues, 23);
91
-			
92
-			ChatterBotThought responseThought = new ChatterBotThought();
93
-			
94
-			responseThought.Text = Utils.StringAtIndex(responseValues, 16);
95
-			
96
-			return responseThought;
97
-		}
98
-		
99
-		public string Think(string text) {
100
-			return Think(new ChatterBotThought() { Text = text }).Text;
101
-		}
102
-	}
21
+
22
+namespace ChatterBotAPI
23
+{
24
+    internal class Cleverbot : ChatterBot
25
+    {
26
+        private readonly int endIndex;
27
+        private readonly string baseUrl;
28
+        private readonly string url;
29
+
30
+        public Cleverbot(string baseUrl, string url, int endIndex)
31
+        {
32
+            this.baseUrl = baseUrl;
33
+            this.url = url;
34
+            this.endIndex = endIndex;
35
+        }
36
+
37
+        public ChatterBotSession CreateSession()
38
+        {
39
+            return new CleverbotSession(baseUrl, url, endIndex);
40
+        }
41
+    }
42
+
43
+    internal class CleverbotSession : ChatterBotSession
44
+    {
45
+        private readonly int endIndex;
46
+        private readonly string baseUrl;
47
+        private readonly string url;
48
+        private readonly IDictionary<string, string> vars;
49
+
50
+        public CleverbotSession(string baseUrl, string url, int endIndex)
51
+        {
52
+            this.baseUrl = baseUrl;
53
+            this.url = url;
54
+            this.endIndex = endIndex;
55
+            vars = new Dictionary<string, string>();
56
+            vars["start"] = "y";
57
+            vars["icognoid"] = "wsf";
58
+            vars["fno"] = "0";
59
+            vars["sub"] = "Say";
60
+            vars["islearning"] = "1";
61
+            vars["cleanslate"] = "false";
62
+        }
63
+
64
+        public ChatterBotThought Think(ChatterBotThought thought)
65
+        {
66
+            vars["stimulus"] = thought.Text;
67
+
68
+            var formData = Utils.ParametersToWWWFormURLEncoded(vars);
69
+            var formDataToDigest = formData.Substring(9, endIndex);
70
+            var formDataDigest = Utils.MD5(formDataToDigest);
71
+            vars["icognocheck"] = formDataDigest;
72
+
73
+            var cookies = Utils.GetCookies(baseUrl);
74
+            
75
+            var response = Utils.Post(url, vars, cookies);
76
+
77
+            var responseValues = response.Split('\r');
78
+
79
+            //vars[""] = Utils.StringAtIndex(responseValues, 0); ??
80
+            vars["sessionid"] = Utils.StringAtIndex(responseValues, 1);
81
+            vars["logurl"] = Utils.StringAtIndex(responseValues, 2);
82
+            vars["vText8"] = Utils.StringAtIndex(responseValues, 3);
83
+            vars["vText7"] = Utils.StringAtIndex(responseValues, 4);
84
+            vars["vText6"] = Utils.StringAtIndex(responseValues, 5);
85
+            vars["vText5"] = Utils.StringAtIndex(responseValues, 6);
86
+            vars["vText4"] = Utils.StringAtIndex(responseValues, 7);
87
+            vars["vText3"] = Utils.StringAtIndex(responseValues, 8);
88
+            vars["vText2"] = Utils.StringAtIndex(responseValues, 9);
89
+            vars["prevref"] = Utils.StringAtIndex(responseValues, 10);
90
+            //vars[""] = Utils.StringAtIndex(responseValues, 11); ??
91
+            vars["emotionalhistory"] = Utils.StringAtIndex(responseValues, 12);
92
+            vars["ttsLocMP3"] = Utils.StringAtIndex(responseValues, 13);
93
+            vars["ttsLocTXT"] = Utils.StringAtIndex(responseValues, 14);
94
+            vars["ttsLocTXT3"] = Utils.StringAtIndex(responseValues, 15);
95
+            vars["ttsText"] = Utils.StringAtIndex(responseValues, 16);
96
+            vars["lineRef"] = Utils.StringAtIndex(responseValues, 17);
97
+            vars["lineURL"] = Utils.StringAtIndex(responseValues, 18);
98
+            vars["linePOST"] = Utils.StringAtIndex(responseValues, 19);
99
+            vars["lineChoices"] = Utils.StringAtIndex(responseValues, 20);
100
+            vars["lineChoicesAbbrev"] = Utils.StringAtIndex(responseValues, 21);
101
+            vars["typingData"] = Utils.StringAtIndex(responseValues, 22);
102
+            vars["divert"] = Utils.StringAtIndex(responseValues, 23);
103
+
104
+            var responseThought = new ChatterBotThought();
105
+
106
+            responseThought.Text = Utils.StringAtIndex(responseValues, 16);
107
+
108
+            return responseThought;
109
+        }
110
+
111
+        public string Think(string text)
112
+        {
113
+            return Think(new ChatterBotThought {Text = text}).Text;
114
+        }
115
+    }
103 116
 }
104 117
\ No newline at end of file
... ...
@@ -1,5 +1,4 @@
1 1
 using System;
2
-
3 2
 using System.Collections.Generic;
4 3
 
5 4
 /*
... ...
@@ -19,42 +18,50 @@ using System.Collections.Generic;
19 18
     You should have received a copy of the GNU Lesser General Public License
20 19
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 20
 */
22
-namespace ChatterBotAPI {
23
-	
24
-	class Pandorabots: ChatterBot {
25
-		private readonly string botid;
26
-		
27
-		public Pandorabots(string botid) {
28
-			this.botid = botid;
29
-		}
30
-		
31
-		public ChatterBotSession CreateSession() {
32
-			return new PandorabotsSession(botid);
33
-		}
34
-	}
35
-	
36
-	class PandorabotsSession: ChatterBotSession {
37
-		private readonly IDictionary<string, string> vars;
38
-		
39
-		public PandorabotsSession(string botid) {
40
-			vars = new Dictionary<string, string>();
41
-			vars["botid"] = botid;
42
-			vars["custid"] = Guid.NewGuid().ToString();
43
-		}
44
-		
45
-		public ChatterBotThought Think(ChatterBotThought thought) {
46
-			vars["input"] = thought.Text;
47
-			
48
-			string response = Utils.Post("http://www.pandorabots.com/pandora/talk-xml", vars);
49
-			
50
-			ChatterBotThought responseThought = new ChatterBotThought();
51
-			responseThought.Text = Utils.XPathSearch(response, "//result/that/text()");
52
-			
53
-			return responseThought;
54
-		}
55
-		
56
-		public string Think(string text) {
57
-			return Think(new ChatterBotThought() { Text = text }).Text;
58
-		}
59
-	}
21
+
22
+namespace ChatterBotAPI
23
+{
24
+    internal class Pandorabots : ChatterBot
25
+    {
26
+        private readonly string botid;
27
+
28
+        public Pandorabots(string botid)
29
+        {
30
+            this.botid = botid;
31
+        }
32
+
33
+        public ChatterBotSession CreateSession()
34
+        {
35
+            return new PandorabotsSession(botid);
36
+        }
37
+    }
38
+
39
+    internal class PandorabotsSession : ChatterBotSession
40
+    {
41
+        private readonly IDictionary<string, string> vars;
42
+
43
+        public PandorabotsSession(string botid)
44
+        {
45
+            vars = new Dictionary<string, string>();
46
+            vars["botid"] = botid;
47
+            vars["custid"] = Guid.NewGuid().ToString();
48
+        }
49
+
50
+        public ChatterBotThought Think(ChatterBotThought thought)
51
+        {
52
+            vars["input"] = thought.Text;
53
+
54
+            var response = Utils.Post("http://www.pandorabots.com/pandora/talk-xml", vars, null);
55
+
56
+            var responseThought = new ChatterBotThought();
57
+            responseThought.Text = Utils.XPathSearch(response, "//result/that/text()");
58
+
59
+            return responseThought;
60
+        }
61
+
62
+        public string Think(string text)
63
+        {
64
+            return Think(new ChatterBotThought {Text = text}).Text;
65
+        }
66
+    }
60 67
 }
61 68
\ No newline at end of file
... ...
@@ -1,11 +1,7 @@
1
-using System;
2
-
3 1
 using System.Collections.Generic;
4 2
 using System.IO;
5 3
 using System.Net;
6 4
 using System.Text;
7
-using System.Web;
8
-using System.Web.Security;
9 5
 using System.Xml.XPath;
10 6
 
11 7
 /*
... ...
@@ -25,55 +21,100 @@ using System.Xml.XPath;
25 21
     You should have received a copy of the GNU Lesser General Public License
26 22
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
27 23
 */
28
-namespace ChatterBotAPI {
29
-	
30
-	static class Utils {
31
-		
32
-		public static string ParametersToWWWFormURLEncoded(IDictionary<string, string> parameters) {
33
-			string wwwFormUrlEncoded = null;
34
-			foreach (string parameterKey in parameters.Keys) {
35
-				string parameterValue = parameters[parameterKey];
36
-				string parameter = string.Format("{0}={1}", HttpUtility.UrlEncode(parameterKey), HttpUtility.UrlEncode(parameterValue));
37
-				if (wwwFormUrlEncoded == null) {
38
-					wwwFormUrlEncoded = parameter;
39
-				} else {
40
-					wwwFormUrlEncoded = string.Format("{0}&{1}", wwwFormUrlEncoded, parameter);
41
-				}
42
-			}
43
-			return wwwFormUrlEncoded;
44
-		}
45
-		
46
-		public static string MD5(string input) {
47
-			return FormsAuthentication.HashPasswordForStoringInConfigFile(input, "MD5");
48
-		}
49
-		
50
-		public static string Post(string url, IDictionary<string, string> parameters) {
51
-			string postData = ParametersToWWWFormURLEncoded(parameters);
52
-			byte[] postDataBytes = Encoding.ASCII.GetBytes(postData);
53
-			
54
-			WebRequest webRequest = WebRequest.Create(url);
55
-			webRequest.Method = "POST";
56
-			webRequest.ContentType = "application/x-www-form-urlencoded";
57
-			webRequest.ContentLength = postDataBytes.Length;
58
-			
59
-			Stream outputStream = webRequest.GetRequestStream();
60
-			outputStream.Write(postDataBytes, 0, postDataBytes.Length);
61
-			outputStream.Close();
62
-			
63
-			WebResponse webResponse = webRequest.GetResponse();
64
-			StreamReader responseStreamReader = new StreamReader(webResponse.GetResponseStream());
65
-			return responseStreamReader.ReadToEnd().Trim();
66
-		}
67
-		
68
-		public static string XPathSearch(string input, string expression) {
69
-			XPathDocument document = new XPathDocument(new MemoryStream(Encoding.ASCII.GetBytes(input)));
70
-			XPathNavigator navigator = document.CreateNavigator();
71
-			return navigator.SelectSingleNode(expression).Value.Trim();
72
-		}
73
-		
74
-		public static string StringAtIndex(string[] strings, int index) {
75
-			if (index >= strings.Length) return "";
76
-			return strings[index];
77
-		}
78
-	}
24
+
25
+namespace ChatterBotAPI
26
+{
27
+    internal static class Utils
28
+    {
29
+        public static string ParametersToWWWFormURLEncoded(IDictionary<string, string> parameters)
30
+        {
31
+            string wwwFormUrlEncoded = null;
32
+            foreach (var parameterKey in parameters.Keys)
33
+            {
34
+                var parameterValue = parameters[parameterKey];
35
+                var parameter = string.Format("{0}={1}", System.Uri.EscapeDataString(parameterKey), System.Uri.EscapeDataString(parameterValue)); 
36
+                if (wwwFormUrlEncoded == null)
37
+                {
38
+                    wwwFormUrlEncoded = parameter;
39
+                }
40
+                else
41
+                {
42
+                    wwwFormUrlEncoded = string.Format("{0}&{1}", wwwFormUrlEncoded, parameter);
43
+                }
44
+            }
45
+            return wwwFormUrlEncoded;
46
+        }
47
+
48
+        public static string MD5(string input)
49
+        {
50
+            // step 1, calculate MD5 hash from input
51
+            var md5 = System.Security.Cryptography.MD5.Create();
52
+            var inputBytes = Encoding.ASCII.GetBytes(input);
53
+            var hash = md5.ComputeHash(inputBytes);
54
+
55
+            // step 2, convert byte array to hex string
56
+            var sb = new StringBuilder();
57
+            for (var i = 0; i < hash.Length; i++)
58
+            {
59
+                sb.Append(hash[i].ToString("X2"));
60
+            }
61
+            return sb.ToString();
62
+        
63
+        }
64
+
65
+        public static CookieCollection GetCookies(string url)
66
+        {
67
+            CookieContainer container = new CookieContainer();
68
+            var request = (HttpWebRequest)WebRequest.Create(url);
69
+            request.Method = "GET";
70
+            request.Headers.Add("UserAgent", "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0;");
71
+            request.ContentType = "text/html";
72
+            request.CookieContainer = container;
73
+
74
+            request.GetResponse();
75
+
76
+            return container.GetCookies(request.RequestUri);
77
+        }
78
+
79
+        public static string Post(string url, IDictionary<string, string> parameters, CookieCollection cookies)
80
+        {
81
+            var postData = ParametersToWWWFormURLEncoded(parameters);
82
+            var postDataBytes = Encoding.ASCII.GetBytes(postData);
83
+
84
+            var request = (HttpWebRequest)WebRequest.Create(url);
85
+
86
+            if (cookies != null)
87
+            {
88
+                var container = new CookieContainer();
89
+                container.Add(cookies);
90
+                request.CookieContainer = container;
91
+            }
92
+
93
+            
94
+            request.Method = "POST";
95
+            request.ContentType = "application/x-www-form-urlencoded";
96
+            request.ContentLength = postDataBytes.Length;
97
+
98
+            var outputStream = request.GetRequestStream();
99
+            outputStream.Write(postDataBytes, 0, postDataBytes.Length);
100
+            outputStream.Close();
101
+
102
+            var response = (HttpWebResponse)request.GetResponse();
103
+            var responseStreamReader = new StreamReader(response.GetResponseStream());
104
+            return responseStreamReader.ReadToEnd().Trim();
105
+        }
106
+
107
+        public static string XPathSearch(string input, string expression)
108
+        {
109
+            var document = new XPathDocument(new MemoryStream(Encoding.ASCII.GetBytes(input)));
110
+            var navigator = document.CreateNavigator();
111
+            return navigator.SelectSingleNode(expression).Value.Trim();
112
+        }
113
+
114
+        public static string StringAtIndex(string[] strings, int index)
115
+        {
116
+            if (index >= strings.Length) return "";
117
+            return strings[index];
118
+        }
119
+    }
79 120
 }
80 121
\ No newline at end of file