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 SpeedportHybridControl.Model;
13 using Newtonsoft.Json;
14 using SpeedportHybridControl.PageModel;
16 namespace SpeedportHybridControl.Data {
17 public class SpeedportHybridAPI : SingletonFactory<SpeedportHybridAPI> {
18 public string _ip = "speedport.ip";
19 private DateTime _lastReboot = DateTime.MinValue;
20 private bool _checkIsActive = false;
21 public string _password;
22 public string _challenge;
24 public string _derivedk;
25 public CookieContainer _cookie = new CookieContainer();
33 * Requests the password-challenge from the router.
37 public string getChallenge () {
38 string response = sendRequest("data/Login.json", "csrf_token=nulltoken&showpw=0&challengev=null");
39 if (response.IsNullOrEmpty())
42 string challenge = string.Empty;
44 JToken jArray = JToken.Parse(response);
46 challenge = jArray.getVar("challengev");
49 catch (Exception ex) {
50 LogManager.WriteToLog(ex.Message);
59 * calculate the derivedk
61 * @param string $password
64 public string getDerviedk () {
65 return _password.sha256().pbkdf2(_challenge.Substring(0, 16));
69 * login into the router with the given password
71 * @param string $password
74 public bool login (string password) {
75 if (password.IsNullOrEmpty()) {
79 _cookie = new CookieContainer();
82 _challenge = getChallenge();
83 _hash = string.Concat(_challenge, ":", password).sha256();
85 string response = sendRequest("data/Login.json", string.Concat("csrf_token=nulltoken&showpw=0&password=", _hash));
86 if (response.IsNullOrEmpty())
89 _cookie.Add(new Cookie("challengev", _challenge) { Domain = "speedport.ip" });
93 JToken jArray = JToken.Parse(response);
94 if (jArray.getVar("login").Equals("success")) {
95 if (isLoggedin().Equals(false)) {
100 _derivedk = getDerviedk();
101 _lastReboot = getLastReboot();
106 catch (Exception ex) {
107 LogManager.WriteToLog(ex.Message);
120 public bool logout () {
121 string response = sendRequest("data/Login.json", string.Concat("csrf_token=", getToken(), "&logout=byby"));
122 if (response.IsNullOrEmpty())
127 JToken jArray = JToken.Parse(response);
128 if (jArray.getVar("status").Equals("ok")) {
129 if (isLoggedin().Equals(true)) {
136 _cookie = new CookieContainer();
137 _lastReboot = DateTime.MinValue;
145 catch (Exception ex) {
146 LogManager.WriteToLog(ex.Message);
155 * check if we are logged in
159 public bool checkLogin () {
160 if (_checkIsActive.Equals(false)) {
161 _checkIsActive = true;
162 if (isLoggedin().Equals(false)) {
163 Console.WriteLine("Session expired, try to relogin");
167 if (login(_password).Equals(false)) {
168 // should we try to relogin? login(_password);...
169 new Thread(() => { LogManager.WriteToLog("Session expired."); }).Start();
172 _cookie = new CookieContainer();
173 _lastReboot = DateTime.MinValue;
177 LoginPageModel lpm = Application.Current.FindResource("LoginPageModel") as LoginPageModel;
178 lpm.LoginCommand.Execute();
179 MainWindowModel mwm = Application.Current.FindResource("MainWindowModel") as MainWindowModel;
180 mwm.SwitchToLoginPage.Execute();
182 new Thread(() => { MessageBox.Show("Session expired.", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Error); }).Start();
183 _checkIsActive = false;
188 _checkIsActive = false;
191 Console.WriteLine("check allready in progress");
198 * check if we are logged in
200 * @param bool ischeck
203 public bool isLoggedin () {
204 string response = sendRequest("data/SecureStatus.json");
205 if (response.IsNullOrEmpty())
210 JToken jArray = JToken.Parse(response);
212 if (jArray.getVar("loginstate").Equals("1")/* && jArray.getVar("login").Equals("true")*/) {
219 catch (Exception ex) {
220 LogManager.WriteToLog(ex.Message);
231 public void reboot () {
232 if (checkLogin().Equals(false))
235 string response = sendRequest("data/Reboot.json", string.Concat("csrf_token=", Uri.EscapeUriString(getToken()), "&reboot_device=true"));
236 if (response.IsNullOrEmpty())
239 JToken jArray = JToken.Parse(response);
240 if (jArray.getVar("status").Equals("ok")) {
241 new Thread(() => { MessageBox.Show("Router Reboot.", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Information); }).Start();
242 LogManager.WriteToLog("Router Reboot.");
245 _cookie = new CookieContainer();
249 LoginPageModel lpm = Application.Current.FindResource("LoginPageModel") as LoginPageModel;
250 lpm.LoginCommand.Execute();
251 MainWindowModel mwm = Application.Current.FindResource("MainWindowModel") as MainWindowModel;
252 mwm.SwitchToLoginPage.Execute();
257 catch (Exception ex) {
258 LogManager.WriteToLog(ex.Message);
269 public bool reconnectLte () {
270 if (checkLogin().Equals(false))
275 string response = sendEnryptedRequest("data/modules.json", string.Concat("lte_reconn=1&csrf_token=", Uri.EscapeUriString(getToken())));
276 if (response.IsNullOrEmpty())
280 JToken jArray = JToken.Parse(response);
284 if (jArray.getVar("status").Equals("ok")) {
291 catch (Exception ex) {
292 LogManager.WriteToLog(ex.Message);
305 public bool reconnectDSL () {
306 if (checkLogin().Equals(false))
311 string response = sendEnryptedRequest("data/Connect.json", string.Concat("csrf_token=", Uri.EscapeUriString(getToken()), "&showpw=0&password=", _hash, "&req_connect=offline"));
312 if (response.IsNullOrEmpty())
315 bool offline = false;
317 JToken jArray = JToken.Parse(response);
321 if (jArray.getVar("status").Equals("ok")) {
327 if (offline.Equals(true)) {
328 response = sendEnryptedRequest("data/Connect.json", string.Concat("csrf_token=", Uri.EscapeUriString(getToken()), "&showpw=0&password=", _hash, "&req_connect=online"));
329 jArray = JToken.Parse(response);
330 if (jArray.getVar("status").Equals("ok")) {
336 catch (Exception ex) {
337 LogManager.WriteToLog(ex.Message);
346 * change dsl connection status
348 * @param string status
351 public bool changeDSLStatus (string status) {
352 if (checkLogin().Equals(false))
355 if (status.Equals("online") || status.Equals("offline")) {
357 string response = sendEnryptedRequest("data/Connect.json", string.Concat("req_connect=", status, "&csrf_token=", Uri.EscapeUriString(getToken())));
358 if (response.IsNullOrEmpty())
361 JToken jArray = JToken.Parse(response);
365 if (jArray.getVar("status").Equals("ok")) {
370 catch (Exception ex) {
371 LogManager.WriteToLog(ex.Message);
381 * change lte connection status
383 * @param string status
386 public bool changeLTEStatus (string status) {
387 if (checkLogin().Equals(false))
390 if (status.Equals("online") || status.Equals("offline")) {
391 if (status.Equals("online"))
394 if (status.Equals("offline"))
397 string response = sendEnryptedRequest("data/Modules.json", string.Concat("use_lte=", status, "&csrf_token=", Uri.EscapeUriString(getToken())));
398 if (response.IsNullOrEmpty())
401 JToken jArray = JToken.Parse(response);
405 if (jArray.getVar("status").Equals("ok")) {
410 catch (Exception ex) {
411 LogManager.WriteToLog(ex.Message);
421 * reset the router to Factory Default
426 public bool resetToFactoryDefault () {
427 if (checkLogin().Equals(false))
432 string response = sendEnryptedRequest("data/resetAllSetting.json", string.Concat("csrf_token=nulltoken&showpw=0&password=", _hash, "&reset_all=true"));
433 if (response.IsNullOrEmpty())
437 JToken jArray = JToken.Parse(response);
438 if (jArray.getVar("status").Equals("ok")) {
444 catch (Exception ex) {
445 LogManager.WriteToLog(ex.Message);
454 * check for firmware update
456 public void checkFirmware () {
457 if (checkLogin().Equals(false))
462 string response = sendRequest("data/checkfirm.json");
463 if (response.IsNullOrEmpty())
467 bool fw_isActual = false;
468 JToken jArray = JToken.Parse(response);
470 if (jArray.getVar("fw_isActual").Equals("1")) {
474 if (fw_isActual.Equals(true)) {
475 // Die Firmware ist aktuell.
476 MessageBox.Show("Die Firmware ist aktuell.", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Information);
479 // Es liegt eine neuere Firmware-Version vor. Möchten Sie diese Version jetzt installieren?
480 MessageBox.Show("Es liegt eine neuere Firmware-Version vor.\nMöchten Sie diese Version jetzt installieren?", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Warning);
485 catch (Exception ex) {
486 LogManager.WriteToLog(ex.Message);
495 public void flushDNS () {
496 if (checkLogin().Equals(false))
501 string response = sendEnryptedRequest("data/dns.json", "op_type=flush_dns_cache");
502 if (response.IsNullOrEmpty())
506 JToken jArray = JToken.Parse(response);
508 if (jArray["DCI"].Count().Equals(0)) {
509 new Thread(() => { MessageBox.Show("DNS cache geleert", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Information); }).Start();
512 new Thread(() => { MessageBox.Show("unable to flush dns cache", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Error); }).Start();
518 catch (Exception ex) {
519 LogManager.WriteToLog(ex.Message);
528 public void clearSyslog () {
529 if (checkLogin().Equals(false))
534 string response = sendEnryptedRequest("data/SystemMessages.json", string.Concat("action_clearlist=true&clear_type=0&", "csrf_token=", getToken()));
535 if (response.IsNullOrEmpty())
539 JToken jArray = JToken.Parse(response);
541 if (jArray.getVar("status").Equals("ok")) {
543 new Thread(() => { MessageBox.Show("Syslog geleert", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Information); }).Start();
547 new Thread(() => { MessageBox.Show("Konnte Syslog nicht leeren.", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Error); }).Start();
552 catch (Exception ex) {
553 LogManager.WriteToLog(ex.Message);
560 * set QueueSkbTimeOut
562 * @param string value
564 public void setQueueSkbTimeOut (string value) {
565 if (checkLogin().Equals(false))
568 string response = sendEnryptedRequest("data/bonding_tr181.json", string.Concat("bonding_QueueSkbTimeOut=", value));
569 if (response.IsNullOrEmpty())
572 TR181PageModel obj = JsonConvert.DeserializeObject<TR181PageModel>(response);
574 if (obj.QueueSkbTimeOut.Equals(value)) {
575 new Thread(() => { MessageBox.Show("QueueSkbTimeOut geändert", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Information); }).Start();
578 new Thread(() => { MessageBox.Show("unable to change QueueSkbTimeOut", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Error); }).Start();
583 catch (Exception ex) {
584 LogManager.WriteToLog(ex.Message);
593 * @param string value
595 public void setAntennaMode (string value) {
596 if (checkLogin().Equals(false))
599 string response = sendEnryptedRequest("data/lteinfo.json", string.Concat("mode_select=", value));
600 if (response.IsNullOrEmpty())
603 LteInfoModel obj = JsonConvert.DeserializeObject<LteInfoModel>(response);
606 if (obj.antenna_mode.Equals("Antennal set to internal")) {
607 antenna_mode = "Inner";
609 else if (obj.antenna_mode.Equals("Antennal set to external")) {
610 antenna_mode = "Outer";
613 antenna_mode = "Auto";
616 if (antenna_mode.Equals(value)) {
617 new Thread(() => { MessageBox.Show("Antennen Modus geändert", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Information); }).Start();
620 new Thread(() => { MessageBox.Show("Antennen Modus ändern Fehlgeschlagen", "Confirmation", MessageBoxButton.OK, MessageBoxImage.Error); }).Start();
627 catch (Exception ex) {
628 LogManager.WriteToLog(ex.Message);
635 * get Last Reboot time
639 public DateTime getLastReboot () {
640 if (_lastReboot.Equals(DateTime.MinValue).Equals(false)) {
644 string response = sendRequest("data/Reboot.json");
646 if (response.IsNullOrEmpty())
649 JToken jArray = JToken.Parse(response);
651 DateTime lastReboot = DateTime.Parse(string.Concat(jArray.getVar("reboot_date"), " ", jArray.getVar("reboot_time")));
659 * get the csrf token from router
663 public string getToken () {
664 string response = sendRequest("html/content/overview/index.html");
665 if (response.IsNullOrEmpty())
668 string a = "csrf_token = \"";
670 string token = response.Substring((response.IndexOf(a) + a.Length), (response.IndexOf(b) - response.IndexOf(a) - a.Length));
676 Console.WriteLine("csrf_token: " + token);
681 * send encrypted request to the router
688 public string sendEnryptedRequest (string path, string post = "", bool cookie = true) {
689 string response = string.Empty;
692 sjcl sjcl = new sjcl();
694 string iv = _challenge.Substring(16, 16);
695 string adata = _challenge.Substring(32, 16);
696 string dKey = _derivedk;
699 // TODO: check if we need this really?
700 if (post.IsNullOrEmpty().Equals(false)) {
701 post = sjcl.encrypt(dKey, post, iv, adata);
705 response = sendRequest(path, post, cookie);
706 // check if the return value is hex (hex = enrypted)
707 if (Regex.IsMatch(response, @"\A\b[0-9a-fA-F]+\b\Z").Equals(true)) {
708 response = sjcl.decrypt(dKey, response, iv, adata);
718 catch (ArgumentOutOfRangeException ex) {
719 LogManager.WriteToLog(ex.Message);
721 catch (Exception ex) {
722 LogManager.WriteToLog(ex.Message);
729 * send request to the router
736 public string sendRequest (string path, string post = "", bool cookie = true) {
737 string response = string.Empty;
739 string url = string.Concat("http://", ip, "/", path, "?lang=de");
741 HttpWebRequest webRequest = WebRequest.Create(url) as HttpWebRequest;
742 /* set timeout to 10 seconds */
743 webRequest.Timeout = 10000;
745 if (cookie.Equals(true)) {
746 webRequest.CookieContainer = _cookie;
749 if (post.IsNullOrEmpty().Equals(false)) {
750 webRequest.Method = "POST";
751 byte[] dataStream = Encoding.UTF8.GetBytes(post);
752 webRequest.ContentLength = dataStream.Length;
753 Stream newStream = webRequest.GetRequestStream();
754 newStream.Write(dataStream, 0, dataStream.Length);
761 WebResponse webResponse = webRequest.GetResponse();
762 StreamReader reader = new StreamReader(webResponse.GetResponseStream());
763 response = reader.ReadToEnd().ToString();
765 webResponse.Dispose();
772 catch (Exception ex) {
773 LogManager.WriteToLog(ex.Message);
779 public string sendRequest2 (string path, Dictionary<string, object> files, string post = "", bool cookie = true) {
780 string response = string.Empty;
783 string url = string.Concat("http://", ip, "/", path, "?lang=de");
785 string boundary = string.Concat("---------------------------", DateTime.Now.Ticks.ToString("x"));
786 byte[] boundaryBytes = Encoding.ASCII.GetBytes(string.Concat("\r\n--", boundary, "\r\n"));
788 HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
789 request.ContentType = string.Concat("multipart/form-data; boundary=", boundary);
790 request.Method = "POST";
791 request.KeepAlive = true;
793 if (cookie.Equals(true)) {
794 request.CookieContainer = _cookie;
797 Stream requestStream = request.GetRequestStream();
799 if (string.IsNullOrEmpty(post).Equals(false)) {
800 byte[] dataStream = Encoding.UTF8.GetBytes(post);
801 requestStream.Write(dataStream, 0, dataStream.Length);
805 if (files != null && files.Count > 0) {
806 foreach (KeyValuePair<string, object> pair in files) {
807 requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
808 if (pair.Value is FormFile) {
809 FormFile file = pair.Value as FormFile;
810 string header = string.Concat("Content-Disposition: form-data; name=\"", pair.Key, "\"; filename=\"", file.Name, "\"\r\nContent-Type: ", file.ContentType, "\r\n\r\n");
811 byte[] bytes = Encoding.UTF8.GetBytes(header);
812 requestStream.Write(bytes, 0, bytes.Length);
813 byte[] buffer = new byte[32768];
815 if (file.Stream == null) {
817 FileStream fileStream = File.OpenRead(file.FilePath);
818 while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) {
819 requestStream.Write(buffer, 0, bytesRead);
824 // upload from given stream
825 while ((bytesRead = file.Stream.Read(buffer, 0, buffer.Length)) != 0)
826 requestStream.Write(buffer, 0, bytesRead);
830 string data = string.Concat("Content-Disposition: form-data; name=\"", pair.Key, "\"\r\n\r\n", pair.Value);
831 byte[] bytes = Encoding.UTF8.GetBytes(data);
832 requestStream.Write(bytes, 0, bytes.Length);
836 byte[] trailer = Encoding.ASCII.GetBytes(string.Concat("\r\n--", boundary, "--\r\n"));
837 requestStream.Write(trailer, 0, trailer.Length);
838 requestStream.Close();
842 WebResponse webResponse = request.GetResponse();
843 Stream responseStream = webResponse.GetResponseStream();
844 StreamReader reader = new StreamReader(responseStream);
845 response = reader.ReadToEnd();
847 webResponse.Dispose();
853 catch (Exception ex) {
854 LogManager.WriteToLog(ex.Message);
861 public class FormFile {
862 public string Name { get; set; }
864 public string ContentType { get; set; }
866 public string FilePath { get; set; }
868 public Stream Stream { get; set; }