Beispiel #1
0
        private string GetExamPage(CoursesTakenType coursesType, bool shouldRecurse = true)
        {
            // AWFUL CODE, BLAME SUSI

            // Send a post request with predefined values of the hidden fields
            string data = string.Format(HiddenFieldValues.FormattedExamFormData, HttpUtility.UrlEncode(this.vstate));

            switch (coursesType)
            {
            case CoursesTakenType.NotTaken:
                data += HiddenFieldValues.NotTakenCoursesFlag;
                break;

            case CoursesTakenType.Taken:
                data += HiddenFieldValues.TakenCoursesFlag;
                break;

            default:
                data += HiddenFieldValues.TakenCoursesFlag + HiddenFieldValues.NotTakenCoursesFlag;
                break;
            }
            WebResponse response = this.SendRequest(SusiPages.ReportExams, data);

            // Since SUSI sucks, in order to get the courses page we first need the value of a special hidden field - _VSTATE.
            // Unfortunately, _VSTATE has different value on other pages, so first need to get its value from the current response,
            // Then send another request with the updated value (which is what the recursion is for)
            if (shouldRecurse)
            {
                ExtractVstate(response);
                return(this.GetExamPage(coursesType, false));
            }

            // If everything else is ok return the whole page
            return(ReadResponseToEnd(response));
        }
Beispiel #2
0
        /// <summary>
        /// Gets a collection of <see cref="CourseInfo"/> that shows all courses that the student has passed successfully.
        /// </summary>
        public IEnumerable <CourseInfo> GetCourses(CoursesTakenType coursesType)
        {
            if (this.Cookies.Count == 0)
            {
                throw new InvalidOperationException("You must login prior to getting info from SUSI");
            }
#if !DEBUG
            try
            {
#endif
            // Get the exam page and parse it
            string examPage       = this.GetExamPage(coursesType);
            HtmlDocument document = new HtmlDocument();
            document.LoadHtml(examPage);

            // Use a magical xpath to get all rows of the courses table, there may be header rows though
            string xpath = @"/html/body/form/table/tr/td/table[@width=""100%""]/tr/td/table/tr[not(@class)]";
            var nodes    = document.DocumentNode.SelectNodes(xpath);

            // Set the culture to BG, else parsing doubles will fail
            CultureInfo culture = Thread.CurrentThread.CurrentCulture;
            Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("bg-BG");

            List <CourseInfo> courseInfos = new List <CourseInfo>();
            foreach (HtmlNode node in nodes)
            {
                // Each tr has 6 tds inside in the following order:
                // Subject Teacher Type(elective or not) Taken Grade Credits
                HtmlNodeCollection children = node.SelectNodes("td");

                // If the first cell contains the following magic word, the row is a header, ignore it
                if (children[0].InnerText.Contains("Предмет"))
                {
                    continue;
                }

                CourseInfo courseInfo = ExtractCourseInfo(children);

                courseInfos.Add(courseInfo);
            }
            // Set the culture back to whatever it was
            Thread.CurrentThread.CurrentCulture = culture;

            return(courseInfos);

#if !DEBUG
        }

        catch (Exception e)
        {
            // In case something failed, throw a new exception
            throw new WebException("Can't load data from SUSI", e);
        }
#endif
        }
Beispiel #3
0
 public void LogCoursesRequest(string ip, CoursesTakenType type)
 {
     writer.WriteLine("[{0}] COURSES: Request about [{1}] courses served to address [{2}].", DateTime.UtcNow, type, ip);
 }
Beispiel #4
0
        /// <summary>
        /// Gets a collection of <see cref="CourseInfo"/> that shows all courses that the student has passed successfully.
        /// </summary>
        public IEnumerable<CourseInfo> GetCourses(CoursesTakenType coursesType)
        {
            if (this.Cookies.Count == 0)
            {
                throw new InvalidOperationException("You must login prior to getting info from SUSI");
            }
            #if !DEBUG
            try
            {
            #endif
            // Get the exam page and parse it
            string examPage = this.GetExamPage(coursesType);
            HtmlDocument document = new HtmlDocument();
            document.LoadHtml(examPage);

            // Use a magical xpath to get all rows of the courses table, there may be header rows though
            string xpath = @"/html/body/form/table/tr/td/table[@width=""100%""]/tr/td/table/tr[not(@class)]";
            var nodes = document.DocumentNode.SelectNodes(xpath);

            // Set the culture to BG, else parsing doubles will fail
            CultureInfo culture = Thread.CurrentThread.CurrentCulture;
            Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("bg-BG");

            List<CourseInfo> courseInfos = new List<CourseInfo>();
            foreach (HtmlNode node in nodes)
            {
                // Each tr has 6 tds inside in the following order:
                // Subject Teacher Type(elective or not) Taken Grade Credits
                HtmlNodeCollection children = node.SelectNodes("td");

                // If the first cell contains the following magic word, the row is a header, ignore it
                if (children[0].InnerText.Contains("Предмет"))
                    continue;

                CourseInfo courseInfo = ExtractCourseInfo(children);

                courseInfos.Add(courseInfo);
            }
            // Set the culture back to whatever it was
            Thread.CurrentThread.CurrentCulture = culture;

            return courseInfos;
            #if !DEBUG
            }
            catch (Exception e)
            {
                // In case something failed, throw a new exception
                throw new WebException("Can't load data from SUSI", e);
            }
            #endif
        }
Beispiel #5
0
        private string GetExamPage(CoursesTakenType coursesType, bool shouldRecurse = true)
        {
            // AWFUL CODE, BLAME SUSI

            // Send a post request with predefined values of the hidden fields
            string data = string.Format(HiddenFieldValues.FormattedExamFormData, HttpUtility.UrlEncode(this.vstate));
            switch (coursesType)
            {
                case CoursesTakenType.NotTaken:
                    data += HiddenFieldValues.NotTakenCoursesFlag;
                    break;
                case CoursesTakenType.Taken:
                    data += HiddenFieldValues.TakenCoursesFlag;
                    break;
                default:
                    data += HiddenFieldValues.TakenCoursesFlag + HiddenFieldValues.NotTakenCoursesFlag;
                    break;

            }
            WebResponse response = this.SendRequest(SusiPages.ReportExams, data);

            // Since SUSI sucks, in order to get the courses page we first need the value of a special hidden field - _VSTATE.
            // Unfortunately, _VSTATE has different value on other pages, so first need to get its value from the current response,
            // Then send another request with the updated value (which is what the recursion is for)
            if (shouldRecurse)
            {
                ExtractVstate(response);
                return this.GetExamPage(coursesType, false);
            }

            // If everything else is ok return the whole page
            return ReadResponseToEnd(response);
        }
Beispiel #6
0
 public void LogCoursesRequest(string ip, CoursesTakenType type)
 {
     writer.WriteLine("[{0}] COURSES: Request about [{1}] courses served to address [{2}].", DateTime.UtcNow, type, ip);
 }