1 using Newtonsoft.Json.Linq;
7 using System.Text.RegularExpressions;
9 using System.Threading;
10 using System.Collections.Generic;
11 using SpeedportHybridControl.Implementations;
12 using Newtonsoft.Json;
13 using SpeedportHybridControl.PageModel;
15 namespace SpeedportHybridControl.Data
17 public class SpeedportHybridAPI : SingletonFactory<SpeedportHybridAPI>
19 public string _ip = "speedport.ip";
20 private DateTime _lastReboot = DateTime.MinValue;
21 private bool _checkIsActive = false;
22 public string _password;
23 public string _challenge;
25 public string _derivedk;
26 public CookieContainer _cookie = new CookieContainer();
35 * Requests the password-challenge from the router.
39 public string getChallenge()
41 string response = sendRequest("data/Login.json", "csrf_token=nulltoken&showpw=0&challengev=null");
42 if (response.IsNullOrEmpty())
45 string challenge = string.Empty;
48 JToken jArray = JToken.Parse(response);
50 challenge = jArray.getVar("challengev");
55 LogManager.WriteToLog(ex.ToString());
64 * calculate the derivedk
66 * @param string $password
69 public string getDerviedk()
71 return _password.sha256().pbkdf2(_challenge.Substring(0, 16));
75 * login into the router with the given password
77 * @param string $password
80 public bool login(string password)
82 if (password.IsNullOrEmpty())
87 _cookie = new CookieContainer();
90 _challenge = getChallenge();
91 _hash = string.Concat(_challenge, ":", password).sha256();
93 string response = sendRequest("data/Login.json", string.Concat("csrf_token=nulltoken&showpw=0&password=", _hash));
94 if (response.IsNullOrEmpty())
97 _cookie.Add(new Cookie("challengev", _challenge) { Domain = "speedport.ip" });
102 JToken jArray = JToken.Parse(response);
103 if (jArray.getVar("login").Equals("success"))
105 if (isLoggedin().Equals(false))
111 _derivedk = getDerviedk();
112 _lastReboot = getLastReboot();
119 LogManager.WriteToLog(ex.ToString());
134 string response = sendRequest("data/Login.json", string.Concat("csrf_token=", getToken(), "&logout=byby"));
135 if (response.IsNullOrEmpty())
141 JToken jArray = JToken.Parse(response);
142 if (jArray.getVar("status").Equals("ok"))
147 _cookie = new CookieContainer();
148 _lastReboot = DateTime.MinValue;
157 LogManager.WriteToLog(ex.ToString());
166 * check if we are logged in
170 public bool checkLogin()
172 if (_checkIsActive.Equals(false))
174 _checkIsActive = true;
175 if (isLoggedin().Equals(false))
179 if (login(_password).Equals(false))
181 // should we try to relogin? login(_password);...
182 new Thread(() => { LogManager.WriteToLog("Session expired."); }).Start();
185 _cookie = new CookieContainer();
186 _lastReboot = DateTime.MinValue;
190 LoginPageModel lpm = Application.Current.FindResource("LoginPageModel") as LoginPageModel;
192 MainWindowModel mwm = Application.Current.FindResource("MainWindowModel") as MainWindowModel;
193 mwm.SwitchToLoginPage.Execute();
195 new Thread(() => { MessageBox.Show("Session expired.", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Error); }).Start();
196 _checkIsActive = false;
201 _checkIsActive = false;
208 * check if we are logged in
210 * @param bool ischeck
213 public bool isLoggedin()
215 string response = sendRequest("data/heartbeat.json");
216 if (response.IsNullOrEmpty())
222 JToken jArray = JToken.Parse(response);
224 if (jArray.getVar("loginstate").Equals("1"))
234 LogManager.WriteToLog(ex.ToString());
247 if (checkLogin().Equals(false))
250 string response = sendRequest("data/Reboot.json", string.Concat("csrf_token=", Uri.EscapeUriString(getToken()), "&reboot_device=true"));
251 if (response.IsNullOrEmpty())
255 JToken jArray = JToken.Parse(response);
256 if (jArray.getVar("status").Equals("ok"))
258 new Thread(() => { MessageBox.Show("Router Reboot.", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Information); }).Start();
259 LogManager.WriteToLog("Router Reboot.");
262 _cookie = new CookieContainer();
266 LoginPageModel lpm = Application.Current.FindResource("LoginPageModel") as LoginPageModel;
267 lpm.LoginCommand.Execute();
268 MainWindowModel mwm = Application.Current.FindResource("MainWindowModel") as MainWindowModel;
269 mwm.SwitchToLoginPage.Execute();
276 LogManager.WriteToLog(ex.ToString());
287 public bool reconnectLte()
289 if (checkLogin().Equals(false))
294 string response = sendEnryptedRequest("data/modules.json", string.Concat("lte_reconn=1&csrf_token=", Uri.EscapeUriString(getToken())));
295 if (response.IsNullOrEmpty())
300 JToken jArray = JToken.Parse(response);
304 if (jArray.getVar("status").Equals("ok"))
314 LogManager.WriteToLog(ex.ToString());
327 public bool reconnectDSL()
329 if (checkLogin().Equals(false))
334 string response = sendEnryptedRequest("data/Connect.json", string.Concat("csrf_token=", Uri.EscapeUriString(getToken()), "&showpw=0&password=", _hash, "&req_connect=offline"));
335 if (response.IsNullOrEmpty())
338 bool offline = false;
341 JToken jArray = JToken.Parse(response);
345 if (jArray.getVar("status").Equals("ok"))
352 if (offline.Equals(true))
354 response = sendEnryptedRequest("data/Connect.json", string.Concat("csrf_token=", Uri.EscapeUriString(getToken()), "&showpw=0&password=", _hash, "&req_connect=online"));
355 jArray = JToken.Parse(response);
356 if (jArray.getVar("status").Equals("ok"))
365 LogManager.WriteToLog(ex.ToString());
374 * change dsl connection status
376 * @param string status
379 public bool changeDSLStatus(string status)
381 if (checkLogin().Equals(false))
384 if (status.Equals("online") || status.Equals("offline"))
387 string response = sendEnryptedRequest("data/Connect.json", string.Concat("req_connect=", status, "&csrf_token=", Uri.EscapeUriString(getToken())));
388 if (response.IsNullOrEmpty())
392 JToken jArray = JToken.Parse(response);
396 if (jArray.getVar("status").Equals("ok"))
404 LogManager.WriteToLog(ex.ToString());
414 * change lte connection status
416 * @param string status
419 public bool changeLTEStatus(string status)
421 if (checkLogin().Equals(false))
424 if (status.Equals("online") || status.Equals("offline"))
426 if (status.Equals("online"))
429 if (status.Equals("offline"))
432 string response = sendEnryptedRequest("data/Modules.json", string.Concat("use_lte=", status, "&csrf_token=", Uri.EscapeUriString(getToken())));
433 if (response.IsNullOrEmpty())
437 JToken jArray = JToken.Parse(response);
441 if (jArray.getVar("status").Equals("ok"))
449 LogManager.WriteToLog(ex.ToString());
459 * reset the router to Factory Default
464 public bool resetToFactoryDefault()
466 if (checkLogin().Equals(false))
471 string response = sendEnryptedRequest("data/resetAllSetting.json", string.Concat("csrf_token=nulltoken&showpw=0&password=", _hash, "&reset_all=true"));
472 if (response.IsNullOrEmpty())
477 JToken jArray = JToken.Parse(response);
478 if (jArray.getVar("status").Equals("ok"))
487 LogManager.WriteToLog(ex.ToString());
496 * check for firmware update
498 public void checkFirmware()
500 if (checkLogin().Equals(false))
505 string response = sendRequest("data/checkfirm.json");
506 if (response.IsNullOrEmpty())
511 bool fw_isActual = false;
512 JToken jArray = JToken.Parse(response);
514 if (jArray.getVar("fw_isActual").Equals("1"))
519 if (fw_isActual.Equals(true))
521 // Die Firmware ist aktuell.
522 MessageBox.Show("Die Firmware ist aktuell.", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Information);
525 // Es liegt eine neuere Firmware-Version vor. Möchten Sie diese Version jetzt installieren?
526 MessageBox.Show("Es liegt eine neuere Firmware-Version vor.\nMöchten Sie diese Version jetzt installieren?", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Warning);
533 LogManager.WriteToLog(ex.ToString());
542 public void flushDNS()
544 if (checkLogin().Equals(false))
549 string response = sendEnryptedRequest("data/dns.json", "op_type=flush_dns_cache");
550 if (response.IsNullOrEmpty())
555 JToken jArray = JToken.Parse(response);
557 if (jArray["DCI"].Count().Equals(0))
559 new Thread(() => { MessageBox.Show("DNS cache geleert", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Information); }).Start();
562 new Thread(() => { MessageBox.Show("unable to flush dns cache", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Error); }).Start();
570 LogManager.WriteToLog(ex.ToString());
579 public void clearSyslog()
581 if (checkLogin().Equals(false))
586 string response = sendEnryptedRequest("data/SystemMessages.json", string.Concat("action_clearlist=true&clear_type=0&", "csrf_token=", getToken()));
587 if (response.IsNullOrEmpty())
592 JToken jArray = JToken.Parse(response);
594 if (jArray.getVar("status").Equals("ok"))
597 new Thread(() => { MessageBox.Show("Syslog geleert", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Information); }).Start();
601 new Thread(() => { MessageBox.Show("Konnte Syslog nicht leeren.", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Error); }).Start();
608 LogManager.WriteToLog(ex.ToString());
615 * set QueueSkbTimeOut
617 * @param string value
619 public void setQueueSkbTimeOut(string value)
621 if (checkLogin().Equals(false))
624 string response = sendEnryptedRequest("data/bonding_tr181.json", string.Concat("bonding_QueueSkbTimeOut=", value));
625 if (response.IsNullOrEmpty())
629 TR181PageModel obj = JsonConvert.DeserializeObject<TR181PageModel>(response);
631 if (obj.QueueSkbTimeOut.Equals(value))
633 new Thread(() => { MessageBox.Show("QueueSkbTimeOut geändert", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Information); }).Start();
636 new Thread(() => { MessageBox.Show("unable to change QueueSkbTimeOut", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Error); }).Start();
643 LogManager.WriteToLog(ex.ToString());
652 * @param string value
654 public void setAntennaMode(string value)
656 if (checkLogin().Equals(false))
659 string response = sendEnryptedRequest("data/lteinfo.json", string.Concat("mode_select=", value));
660 if (response.IsNullOrEmpty())
664 LteInfoModel obj = JsonConvert.DeserializeObject<LteInfoModel>(response);
667 if (obj.antenna_mode.Equals("Antennal set to internal"))
669 antenna_mode = "Inner";
671 else if (obj.antenna_mode.Equals("Antennal set to external"))
673 antenna_mode = "Outer";
676 antenna_mode = "Auto";
679 if (antenna_mode.Equals(value))
681 new Thread(() => { MessageBox.Show("Antennen Modus geändert", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Information); }).Start();
684 new Thread(() => { MessageBox.Show("Antennen Modus ändern Fehlgeschlagen", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Error); }).Start();
693 LogManager.WriteToLog(ex.ToString());
700 * get Last Reboot time
704 public DateTime getLastReboot()
706 if (_lastReboot.Equals(DateTime.MinValue).Equals(false))
711 string response = sendRequest("data/Reboot.json");
713 if (response.IsNullOrEmpty())
716 JToken jArray = JToken.Parse(response);
718 DateTime lastReboot = DateTime.Parse(string.Concat(jArray.getVar("reboot_date"), " ", jArray.getVar("reboot_time")));
726 * get the csrf token from router
730 public string getToken()
732 string response = sendRequest("html/content/overview/index.html");
733 if (response.IsNullOrEmpty())
736 string a = "csrf_token = \"";
738 string token = response.Substring((response.IndexOf(a) + a.Length), (response.IndexOf(b) - response.IndexOf(a) - a.Length));
748 * send encrypted request to the router
755 public string sendEnryptedRequest(string path, string post = "", bool cookie = true)
757 string response = string.Empty;
761 sjcl sjcl = new sjcl();
763 string iv = _challenge.Substring(16, 16);
764 string adata = _challenge.Substring(32, 16);
765 string dKey = _derivedk;
768 // TODO: check if we need this really?
769 if (post.IsNullOrEmpty().Equals(false))
771 post = sjcl.encrypt(dKey, post, iv, adata);
775 response = sendRequest(path, post, cookie);
776 // check if the return value is hex (hex = enrypted)
777 if (Regex.IsMatch(response, @"\A\b[0-9a-fA-F]+\b\Z").Equals(true))
779 response = sjcl.decrypt(dKey, response, iv, adata);
789 catch (ArgumentOutOfRangeException ex)
791 LogManager.WriteToLog(ex.ToString());
795 LogManager.WriteToLog(ex.ToString());
802 * send request to the router
809 public string sendRequest(string path, string post = "", bool cookie = true)
811 string response = string.Empty;
814 string url = string.Concat("http://", ip, "/", path, "?lang=de");
816 HttpWebRequest webRequest = WebRequest.Create(url) as HttpWebRequest;
817 /* set timeout to 10 seconds */
818 webRequest.Timeout = 10000;
820 if (cookie.Equals(true))
822 webRequest.CookieContainer = _cookie;
825 if (post.IsNullOrEmpty().Equals(false))
827 webRequest.Method = "POST";
828 byte[] dataStream = Encoding.UTF8.GetBytes(post);
829 webRequest.ContentLength = dataStream.Length;
830 Stream newStream = webRequest.GetRequestStream();
831 newStream.Write(dataStream, 0, dataStream.Length);
838 WebResponse webResponse = webRequest.GetResponse();
839 StreamReader reader = new StreamReader(webResponse.GetResponseStream());
840 response = reader.ReadToEnd().ToString();
842 webResponse.Dispose();
851 LogManager.WriteToLog(ex.ToString());
857 public string sendRequest2(string path, Dictionary<string, object> files, string post = "", bool cookie = true)
859 string response = string.Empty;
863 string url = string.Concat("http://", ip, "/", path, "?lang=de");
865 string boundary = string.Concat("---------------------------", DateTime.Now.Ticks.ToString("x"));
866 byte[] boundaryBytes = Encoding.ASCII.GetBytes(string.Concat("\r\n--", boundary, "\r\n"));
868 HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
869 request.ContentType = string.Concat("multipart/form-data; boundary=", boundary);
870 request.Method = "POST";
871 request.KeepAlive = true;
873 if (cookie.Equals(true))
875 request.CookieContainer = _cookie;
878 Stream requestStream = request.GetRequestStream();
880 if (string.IsNullOrEmpty(post).Equals(false))
882 byte[] dataStream = Encoding.UTF8.GetBytes(post);
883 requestStream.Write(dataStream, 0, dataStream.Length);
887 if (files != null && files.Count > 0)
889 foreach (KeyValuePair<string, object> pair in files)
891 requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
892 if (pair.Value is FormFile)
894 FormFile file = pair.Value as FormFile;
895 string header = string.Concat("Content-Disposition: form-data; name=\"", pair.Key, "\"; filename=\"", file.Name, "\"\r\nContent-Type: ", file.ContentType, "\r\n\r\n");
896 byte[] bytes = Encoding.UTF8.GetBytes(header);
897 requestStream.Write(bytes, 0, bytes.Length);
898 byte[] buffer = new byte[32768];
900 if (file.Stream == null)
903 FileStream fileStream = File.OpenRead(file.FilePath);
904 while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
906 requestStream.Write(buffer, 0, bytesRead);
911 // upload from given stream
912 while ((bytesRead = file.Stream.Read(buffer, 0, buffer.Length)) != 0)
913 requestStream.Write(buffer, 0, bytesRead);
917 string data = string.Concat("Content-Disposition: form-data; name=\"", pair.Key, "\"\r\n\r\n", pair.Value);
918 byte[] bytes = Encoding.UTF8.GetBytes(data);
919 requestStream.Write(bytes, 0, bytes.Length);
923 byte[] trailer = Encoding.ASCII.GetBytes(string.Concat("\r\n--", boundary, "--\r\n"));
924 requestStream.Write(trailer, 0, trailer.Length);
925 requestStream.Close();
929 WebResponse webResponse = request.GetResponse();
930 Stream responseStream = webResponse.GetResponseStream();
931 StreamReader reader = new StreamReader(responseStream);
932 response = reader.ReadToEnd();
934 webResponse.Dispose();
942 LogManager.WriteToLog(ex.ToString());
949 public class FormFile
951 public string Name { get; set; }
953 public string ContentType { get; set; }
955 public string FilePath { get; set; }
957 public Stream Stream { get; set; }