using System; using System.Linq; using System.Net.Http; using Android.App; using Android.Content; using Android.Content.PM; using Android.OS; using Android.Preferences; using Android.Support.V7.App; using Android.Text.Method; using Android.Views; using Android.Widget; using AngleSharp.Html.Dom; using AngleSharp.Html.Parser; using GUTSchedule.Models; using GUTSchedule; using GUTSchedule.Droid.Fragments; namespace GUTSchedule.Droid.Activities { [Activity] public class MainActivity : AppCompatActivity { Button start, end, export; Button forDay, forWeek, forMonth, forSemester; Spinner faculty, course, group, reminder, calendar; CheckBox groupTitle, authorize; TextView error; LinearLayout studentParams, profParams; EditText email, password; ISharedPreferences prefs; protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); SetContentView(Resource.Layout.Main); PackageInfo version = PackageManager.GetPackageInfo(PackageName, PackageInfoFlags.MatchAll); FindViewById(Resource.Id.version).Text = $"v{version.VersionName} (ci-id #{version.VersionCode})"; prefs = PreferenceManager.GetDefaultSharedPreferences(this); AssignVariables(); faculty.SetList(this, Data.Faculties.Select(i => i.Name)); int s = Data.Faculties.FindIndex(i => i.Id == prefs.GetString("Faculty", "-123")); faculty.SetSelection(s == -1 ? 0 : s); course.SetList(this, "1234".ToCharArray()); course.SetSelection(prefs.GetInt("Course", 0)); // IDK why but this shit triggers events anyway (even if they are set in the next line. It seem to be that there's some asynchronous shit somewhere there) // P.S. Fuck Android AddEvents(); // Settings spinners' dropdown lists content reminder.SetList(this, new[] { Resources.GetText(Resource.String.noReminderOption), Resources.GetText(Resource.String.inTimeReminderOption), Resources.GetText(Resource.String.fiveMinuteReminderOption), Resources.GetText(Resource.String.tenMinuteReminderOption) }); reminder.SetSelection(prefs.GetInt("Reminder", 0)); calendar.SetList(this, Calendar.Calendars.Select(i => i.Name)); s = Calendar.Calendars.FindIndex(i => i.Id == prefs.GetString("Calendar", "-123")); calendar.SetSelection(s == -1 ? 0 : s); end.Text = Data.EndDate.ToShortDateString(); start.Text = Data.StartDate.ToShortDateString(); groupTitle.Checked = prefs.GetBoolean("AddGroupToHeader", false); authorize.Checked = prefs.GetBoolean("Authorize", true); email.Text = prefs.GetString("email", ""); password.Text = prefs.GetString("password", ""); } private async void Export_Click(object sender, EventArgs e) { error.Visibility = ViewStates.Gone; if (Data.StartDate > Data.EndDate) { error.Text = Resources.GetText(Resource.String.invalidDateRangeError); error.Visibility = ViewStates.Visible; return; } HttpClient client = null; bool? isProf = null; if (authorize.Checked) { Toast.MakeText(ApplicationContext, Resources.GetText(Resource.String.authorizationState), ToastLength.Short).Show(); if (string.IsNullOrWhiteSpace(email.Text) || string.IsNullOrWhiteSpace(password.Text)) { error.Text = Resources.GetText(Resource.String.invalidAuthorizationError); error.Visibility = ViewStates.Visible; return; } export.Enabled = false; client = new HttpClient(); await client.GetAsync("https://cabs.itut.ru/cabinet/"); using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://cabs.itut.ru/cabinet/lib/autentificationok.php"); request.SetContent( ("users", email.Text), ("parole", password.Text)); HttpResponseMessage response = await client.SendAsync(request); string responseContent = await response.GetString(); export.Enabled = true; if (!response.IsSuccessStatusCode) { error.Text = $"{Resources.GetText(Resource.String.authorizationError)}: {response.StatusCode}: {responseContent}"; error.Visibility = ViewStates.Visible; return; } if (!responseContent.StartsWith("1", StringComparison.OrdinalIgnoreCase)) { error.Text = $"{Resources.GetText(Resource.String.invalidCredentialError)} ({string.Join("; ", responseContent.Replace("error=", "", StringComparison.OrdinalIgnoreCase).Split('|'))})"; error.Visibility = ViewStates.Visible; return; } export.Enabled = false; HttpResponseMessage verificationResponse = await client.GetAsync("https://cabs.itut.ru/cabinet/?login=yes"); export.Enabled = true; IHtmlDocument doc = new HtmlParser().ParseDocument(await verificationResponse.GetString()); if (doc.QuerySelectorAll("option").Any(i => i.TextContent.Contains("Сотрудник"))) isProf = true; else isProf = false; Data.Groups = null; // Если ты это читаешь и у тебя возникли вопросы по типу "А какого хуя творится в коде ниже?!", то во-первых: // According to this SO thread: https://stackoverflow.com/questions/1925486/android-storing-username-and-password // I consider Preferences as safe enough method for storing credentials // А во-вторых, даже такой казалось бы небезопасный метод хранения учетных данных в сто раз надежнее того дерьма, // что творится на серверах Бонча (я не шучу, там все ОЧЕНЬ плохо) // Ну и в-третьих: Андроид - это пиздец и настоящий ад разработчика. И если бы была моя воля, я бы под него никогда не писал #FuckAndroid // З.Ы. Помнишь про второй пункт? Так вот, если ты используешь такой же пароль как в ЛК где-то еще, настоятельно рекомендую его поменять PreferenceManager.GetDefaultSharedPreferences(this).Edit().PutString("email", email.Text).Apply(); PreferenceManager.GetDefaultSharedPreferences(this).Edit().PutString("password", password.Text).Apply(); } else { if (Data.Groups.Count < 1) { error.Text = Resources.GetText(Resource.String.groupSelectionError); error.Visibility = ViewStates.Visible; return; } } // Forming export parameters Data.DataSet = new DataSet { Faculty = Data.Faculties[faculty.SelectedItemPosition].Id, Group = Data.Groups?[group.SelectedItemPosition].Id, Course = course.SelectedItemPosition + 1, AddGroupToTitle = groupTitle.Checked, Calendar = Calendar.Calendars[calendar.SelectedItemPosition].Id, Reminder = (reminder.SelectedItemPosition - 1) * 5, HttpClient = client, IsProfessor = isProf }; StartActivity(new Intent(this, typeof(ExportActivity))); } private async void End_Click(object sender, EventArgs e) { Data.EndDate = await new DatePickerFragment().GetDate(SupportFragmentManager, Data.EndDate); end.Text = Data.EndDate.ToShortDateString(); } private async void Start_Click(object sender, EventArgs e) { Data.StartDate = await new DatePickerFragment().GetDate(SupportFragmentManager, Data.StartDate); start.Text = Data.StartDate.ToShortDateString(); } private async void UpdateGroupsList() { if (course.SelectedItem == null) return; await Parser.LoadGroups(Data.Faculties[faculty.SelectedItemPosition].Id, course.SelectedItemPosition + 1); group.SetList(this, Data.Groups.Select(i => i.Name)); int s = Data.Groups?.FindIndex(i => i.Id == prefs.GetString("Group", "-123")) ?? 0; group.SetSelection(s == -1 ? 0 : s); } private void SetDate(int days) { Data.EndDate = Data.StartDate.AddDays(days); end.Text = Data.EndDate.ToShortDateString(); } #region Init stuff private void AssignVariables() { start = FindViewById