From e8f29f14141e7cdec43f32c8176471e352ce1d8b Mon Sep 17 00:00:00 2001 From: Christopher Baines Date: Sat, 17 Mar 2012 23:50:08 +0000 Subject: Initial Commit. --- .gitignore | 9 ++ .project | 17 +++ README | 1 + libs/backport-util-concurrent.jar | Bin 0 -> 331716 bytes libs/commons-codec-1.6.jar | Bin 0 -> 232771 bytes libs/commons-io-2.1.jar | Bin 0 -> 163151 bytes libs/commons-lang-2.6.jar | Bin 0 -> 284220 bytes libs/commons-logging-1.1.1.jar | Bin 0 -> 60841 bytes libs/httpclient-4.1.3.jar | Bin 0 -> 352585 bytes libs/httpcore-4.1.4.jar | Bin 0 -> 181409 bytes libs/ical4j-1.0.3.jar | Bin 0 -> 988578 bytes src/net/cbaines/suca/CalendarApplet.java | 82 ++++++++++++ src/net/cbaines/suca/SotonCalendarFetcher.java | 172 +++++++++++++++++++++++++ src/net/cbaines/suca/SotonCalendarParser.java | 151 ++++++++++++++++++++++ 14 files changed, 432 insertions(+) create mode 100644 .gitignore create mode 100644 .project create mode 100644 README create mode 100644 libs/backport-util-concurrent.jar create mode 100644 libs/commons-codec-1.6.jar create mode 100644 libs/commons-io-2.1.jar create mode 100644 libs/commons-lang-2.6.jar create mode 100644 libs/commons-logging-1.1.1.jar create mode 100644 libs/httpclient-4.1.3.jar create mode 100644 libs/httpcore-4.1.4.jar create mode 100644 libs/ical4j-1.0.3.jar create mode 100644 src/net/cbaines/suca/CalendarApplet.java create mode 100644 src/net/cbaines/suca/SotonCalendarFetcher.java create mode 100644 src/net/cbaines/suca/SotonCalendarParser.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7cffa4c --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +bin/ +*.class +*.temp +*.bak +*~ +*.tmp +.settings/ +.metadata/ +.classpath diff --git a/.project b/.project new file mode 100644 index 0000000..3ea866c --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + SouthamptonUniversityCalendarApplet + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/README b/README new file mode 100644 index 0000000..56a5d4c --- /dev/null +++ b/README @@ -0,0 +1 @@ +Java Applet for using the University of Southampton Student Timetable. diff --git a/libs/backport-util-concurrent.jar b/libs/backport-util-concurrent.jar new file mode 100644 index 0000000..3a4c279 Binary files /dev/null and b/libs/backport-util-concurrent.jar differ diff --git a/libs/commons-codec-1.6.jar b/libs/commons-codec-1.6.jar new file mode 100644 index 0000000..ee1bc49 Binary files /dev/null and b/libs/commons-codec-1.6.jar differ diff --git a/libs/commons-io-2.1.jar b/libs/commons-io-2.1.jar new file mode 100644 index 0000000..b5c7d69 Binary files /dev/null and b/libs/commons-io-2.1.jar differ diff --git a/libs/commons-lang-2.6.jar b/libs/commons-lang-2.6.jar new file mode 100644 index 0000000..98467d3 Binary files /dev/null and b/libs/commons-lang-2.6.jar differ diff --git a/libs/commons-logging-1.1.1.jar b/libs/commons-logging-1.1.1.jar new file mode 100644 index 0000000..8758a96 Binary files /dev/null and b/libs/commons-logging-1.1.1.jar differ diff --git a/libs/httpclient-4.1.3.jar b/libs/httpclient-4.1.3.jar new file mode 100644 index 0000000..dfa8793 Binary files /dev/null and b/libs/httpclient-4.1.3.jar differ diff --git a/libs/httpcore-4.1.4.jar b/libs/httpcore-4.1.4.jar new file mode 100644 index 0000000..1606a2e Binary files /dev/null and b/libs/httpcore-4.1.4.jar differ diff --git a/libs/ical4j-1.0.3.jar b/libs/ical4j-1.0.3.jar new file mode 100644 index 0000000..bf38033 Binary files /dev/null and b/libs/ical4j-1.0.3.jar differ diff --git a/src/net/cbaines/suca/CalendarApplet.java b/src/net/cbaines/suca/CalendarApplet.java new file mode 100644 index 0000000..2b425fd --- /dev/null +++ b/src/net/cbaines/suca/CalendarApplet.java @@ -0,0 +1,82 @@ +package net.cbaines.suca; + +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; + +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; + +import org.apache.commons.io.IOUtils; + +@SuppressWarnings("serial") +public class CalendarApplet extends JApplet { + + JTextField usernameTextField; + JPasswordField passwordTextField; + + JTextArea csvTextArea; + + public void init() { + // Execute a job on the event-dispatching thread: + // creating this applet's GUI. + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + createGUI(); + } + }); + } catch (Exception e) { + System.err.println("createGUI didn't successfully complete"); + } + } + + void createGUI() { + JPanel loginPanel = new JPanel(); + JLabel usernameLabel = new JLabel("Username"); + loginPanel.add(usernameLabel); + usernameTextField = new JTextField(10); + loginPanel.add(usernameTextField); + + JLabel passwordLabel = new JLabel("Password"); + loginPanel.add(passwordLabel); + passwordTextField = new JPasswordField(10); + loginPanel.add(passwordTextField); + + JButton go = new JButton("Go"); + loginPanel.add(go); + + JPanel csvPanel = new JPanel(); + JButton downloadCsv = new JButton("Donwload csv"); + csvPanel.add(downloadCsv); + + csvTextArea = new JTextArea(100, 100); + csvPanel.add(new JScrollPane(csvTextArea)); + + loginPanel.add(csvPanel); + + go.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent arg0) { + String csvString = new SotonCalendarFetcher(usernameTextField.getText(), String + .valueOf(passwordTextField.getPassword())).fetchAndParseTimetable(); + + csvTextArea.setText(csvString); + + } + }); + + getContentPane().add(loginPanel, BorderLayout.CENTER); + + } +} diff --git a/src/net/cbaines/suca/SotonCalendarFetcher.java b/src/net/cbaines/suca/SotonCalendarFetcher.java new file mode 100644 index 0000000..633b898 --- /dev/null +++ b/src/net/cbaines/suca/SotonCalendarFetcher.java @@ -0,0 +1,172 @@ +package net.cbaines.suca; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.cookie.Cookie; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.protocol.HTTP; + +public class SotonCalendarFetcher { + private String username; + private String password; + + public SotonCalendarFetcher(String username, String password) { + this.username = username; + this.password = password; + } + + public String fetchAndParseTimetable() { + DefaultHttpClient httpclient = new DefaultHttpClient(); + try { + HttpGet httpget = new HttpGet( + "https://www.adminservices.soton.ac.uk/adminweb/servlet/login"); + + HttpResponse response = httpclient.execute(httpget); + HttpEntity entity = response.getEntity(); + + // System.out.println("Login form get: " + + // response.getStatusLine()); + // EntityUtils.consume(entity); + if (entity != null) { + try { + entity.consumeContent(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + // System.out.println("Initial set of cookies:"); + List cookies = httpclient.getCookieStore().getCookies(); + if (cookies.isEmpty()) { + // System.out.println("None"); + } else { + for (int i = 0; i < cookies.size(); i++) { + // System.out.println("- " + cookies.get(i).toString()); + } + } + + HttpPost httpost = new HttpPost( + "https://www.adminservices.soton.ac.uk/adminweb/servlet/login"); + + List nvps = new ArrayList(); + nvps.add(new BasicNameValuePair("user", username)); + nvps.add(new BasicNameValuePair("pwd", password)); + System.out.println(username + password); + + httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); + + response = httpclient.execute(httpost); + entity = response.getEntity(); + + for (Header header : response.getAllHeaders()) { + // System.out.println("header: " + header.getName() + " : " + + // header.getValue()); + } + + // System.out.println("Login form get: " + + // response.getStatusLine()); + // EntityUtils.consume(entity); + BufferedReader br = new BufferedReader(new InputStreamReader( + entity.getContent())); + String line; + while ((line = br.readLine()) != null) { + // Log.v(TAG, line); + } + + // System.out.println("Post logon cookies:"); + cookies = httpclient.getCookieStore().getCookies(); + if (cookies.isEmpty()) { + // System.out.println("None"); + } else { + for (int i = 0; i < cookies.size(); i++) { + // System.out.println("- " + cookies.get(i).toString()); + } + } + + httpost = new HttpPost( + "https://www.adminservices.soton.ac.uk/adminweb/jsp/timetables/timetablesController.jsp?comm=studdisplay&style=+format¶mweeks=1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;35;36;37;38;39;40;41;42;43;44;45;46;47;48;49;50;51;52"); + + nvps = new ArrayList(); + nvps.add(new BasicNameValuePair("format", "list")); + + httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); + + response = httpclient.execute(httpost); + entity = response.getEntity(); + + for (Header header : response.getAllHeaders()) { + // System.out.println("header: " + header.getName() + " : " + + // header.getValue()); + } + + System.out.println("Second post get: " + response.getStatusLine()); + // EntityUtils.consume(entity); + br = new BufferedReader(new InputStreamReader(entity.getContent())); + while ((line = br.readLine()) != null) { + // System.out.println(line); + } + + httpost = new HttpPost( + "https://www.adminservices.soton.ac.uk/adminweb/jsp/timetables/timetablesController.jsp?comm=studdisplay&style=+format¶mweeks=1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;35;36;37;38;39;40;41;42;43;44;45;46;47;48;49;50;51;52"); + + nvps = new ArrayList(); + nvps.add(new BasicNameValuePair("format", "list")); + + httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); + + response = httpclient.execute(httpost); + entity = response.getEntity(); + + for (Header header : response.getAllHeaders()) { + // System.out.println("header: " + header.getName() + " : " + + // header.getValue()); + } + + System.out.println("Second post get: " + response.getStatusLine()); + // EntityUtils.consume(entity); + br = new BufferedReader(new InputStreamReader(entity.getContent())); + while ((line = br.readLine()) != null) { + // Log.v(TAG, line); + } + + httpost = new HttpPost( + "https://www.adminservices.soton.ac.uk/adminweb/timetables/ttdownload/.csv"); + + nvps = new ArrayList(); + nvps.add(new BasicNameValuePair("format", "list")); + + httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); + + response = httpclient.execute(httpost); + entity = response.getEntity(); + + return IOUtils.toString(entity.getContent()); + + } catch (IllegalStateException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + // When HttpClient instance is no longer needed, + // shut down the connection manager to ensure + // immediate deallocation of all system resources + httpclient.getConnectionManager().shutdown(); + } + return null; + } +} diff --git a/src/net/cbaines/suca/SotonCalendarParser.java b/src/net/cbaines/suca/SotonCalendarParser.java new file mode 100644 index 0000000..6e9a9ac --- /dev/null +++ b/src/net/cbaines/suca/SotonCalendarParser.java @@ -0,0 +1,151 @@ +package net.cbaines.suca; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.URISyntaxException; +import java.text.ParseException; +import java.util.Arrays; +import java.util.Calendar; +import java.util.GregorianCalendar; + +import net.fortuna.ical4j.data.CalendarParser; +import net.fortuna.ical4j.data.ContentHandler; +import net.fortuna.ical4j.data.ParserException; +import net.fortuna.ical4j.model.Component; +import net.fortuna.ical4j.model.DateTime; +import net.fortuna.ical4j.model.Property; + +public class SotonCalendarParser implements CalendarParser { + private final static String TAG = "SotonCalendarParser"; + + /** + * Start dates for the Autumn term's for each Academic Year starting from + * 2011 to + */ + // private static final GregorianCalendar[] startOfAutumnTerm = {new + // GregorianCalendar(2011, Calendar.SEPTEMBER, 19),new + // GregorianCalendar(2011, Calendar.SEPTEMBER, 19) + + private Calendar startOfYear = new GregorianCalendar(2011, + Calendar.SEPTEMBER, 19); + + public void parse(InputStream in, ContentHandler handler) + throws IOException, ParserException { + parse(new InputStreamReader(in), handler); + } + + public void parse(Reader in, ContentHandler handler) throws IOException, + ParserException { + parse(new BufferedReader(in, 3), handler); + } + + public void parse(BufferedReader in, ContentHandler handler) + throws IOException, ParserException { + + try { + handler.startCalendar(); + handler.startProperty(Property.NAME); + handler.propertyValue("2.0"); + handler.endProperty(Property.NAME); + handler.startProperty(Property.PRODID); + handler.propertyValue("-//Chris Baines + Henco Appel//SouthamptonUniversityOrganiser//EN"); + handler.endProperty(Property.NAME); + String line; + while ((line = in.readLine()) != null) { + if (!line.trim().equals("")) { + System.out.println("Line: " + line); + String[] lecture = line.split("\",\""); + // Remove the starting " off of the date + lecture[0] = lecture[0].substring(1, + lecture[0].length() - 1); + // Remove the trailing " off of the weeks + lecture[6] = lecture[6].substring(0, + lecture[0].length() - 1); + String[] people = lecture[4].split(","); + String[] weeks = lecture[6].split("[\\-,]"); + // System.out.println(Arrays.toString(lecture)); + for (int i = 0; i < weeks.length; i += 2) { + int weeksStart = Integer.parseInt(weeks[i].trim()); + int weeksEnd = weeksStart; + if (i + 1 < weeks.length) { + weeksEnd = Integer.parseInt(weeks[i + 1].trim()); + } + for (int week = weeksStart; week <= weeksEnd; week++) { + // System.out.println(week + + // Arrays.toString(lecture)); + createEvent(lecture, handler, week); + } + } + + } + } + handler.endCalendar(); + } catch (ParseException e) { + e.printStackTrace(); + } catch (URISyntaxException e) { + e.printStackTrace(); + } catch (NumberFormatException e) { + e.printStackTrace(); + } + } + + // void String getRecuranceRule(String weeks) { + // StringBuilder rrule = new StringBuilder(50); + // rrule.append("RRULE:FREQ=WEEKLY;"); + // + // } + + private void createEvent(String[] lecture, ContentHandler handler, int week) + throws ParseException, URISyntaxException, IOException, + NumberFormatException { + handler.startComponent(Component.VEVENT); + handler.startProperty(Property.UID); + handler.propertyValue("email"); + handler.endProperty(Property.UID); + handler.startProperty(Property.DTSTAMP); + handler.propertyValue(new DateTime(java.util.Calendar.getInstance() + .getTime()).toString()); + handler.endProperty(Property.DTSTAMP); + // handler.startProperty(Property.ORGANIZER); + // handler.propertyValue("Organiser"); + // handler.endProperty(Property.ORGANIZER); + Calendar time = (Calendar) startOfYear.clone(); + int day = 0; + if (lecture[0].equals("Monday")) { + day = 0; + } else if (lecture[0].equals("Tuesday")) { + day = 1; + } else if (lecture[0].equals("Wednesday")) { + day = 2; + } else if (lecture[0].equals("Thursday")) { + day = 3; + } else if (lecture[0].equals("Friday")) { + day = 4; + } else { + throw new ParseException(Arrays.toString(lecture), 0); + } + time.add(Calendar.DAY_OF_MONTH, day); + time.set(Calendar.HOUR_OF_DAY, + Integer.parseInt(lecture[1].substring(0, 2))); + time.add(Calendar.WEEK_OF_YEAR, week); + handler.startProperty(Property.DTSTART); + handler.propertyValue(new DateTime(time.getTime()).toString()); + handler.endProperty(Property.DTSTART); + time.set(Calendar.HOUR_OF_DAY, + Integer.parseInt(lecture[2].substring(0, 2))); + handler.startProperty(Property.DTEND); + handler.propertyValue(new DateTime(time.getTime()).toString()); + handler.endProperty(Property.DTEND); + handler.startProperty(Property.LOCATION); + handler.propertyValue(lecture[5]); + handler.endProperty(Property.LOCATION); + handler.startProperty(Property.SUMMARY); + handler.propertyValue(lecture[3] + " with " + lecture[4] + " in " + + lecture[5]); + handler.endProperty(Property.SUMMARY); + handler.endComponent(Component.VEVENT); + } +} -- cgit v1.2.3