Index: src/mlx/acft.py
===================================================================
--- src/mlx/acft.py	(revision 170)
+++ src/mlx/acft.py	(revision 184)
@@ -66,5 +66,5 @@
         # queried from it, so the model should have a reference to the GUI as
         # well and access such data via the GUI!
-        if flight.config.onlineACARS:
+        if flight.config.onlineACARS and not flight.entranceExam:
             self._checkers.append(checks.ACARSSender(flight._gui))
 
@@ -173,7 +173,9 @@
                 self._logV1R2()
             elif newStage==const.STAGE_TAXIAFTERLAND:
-                bookedFlight = self._flight.bookedFlight
-                config = self._flight.config
+                flight = self._flight
+                bookedFlight = flight.bookedFlight
+                config = flight.config
                 if config.onlineGateSystem and \
+                   not flight.entranceExam and \
                    bookedFlight.arrivalICAO=="LHBP" and \
                    config.isMessageTypeFS(const.MESSAGETYPE_GATE_SYSTEM):
Index: src/mlx/checks.py
===================================================================
--- src/mlx/checks.py	(revision 183)
+++ src/mlx/checks.py	(revision 184)
@@ -750,5 +750,6 @@
         """Get the limit if we are in the right state."""
         return aircraft.mlw if flight.stage==const.STAGE_LANDING and \
-                               state.onTheGround else None
+                               state.onTheGround and \
+                               not flight.entranceExam else None
 
 #---------------------------------------------------------------------------------------
@@ -762,5 +763,6 @@
     def getLimit(self, flight, aircraft, state):
         """Get the limit if we are in the right state."""
-        return aircraft.mtow if flight.stage==const.STAGE_TAKEOFF else None
+        return aircraft.mtow if flight.stage==const.STAGE_TAKEOFF and \
+                             not flight.entranceExam else None
 
 #---------------------------------------------------------------------------------------
@@ -774,5 +776,5 @@
     def getLimit(self, flight, aircraft, state):
         """Get the limit if we are in the right state."""
-        return aircraft.mzfw
+        return aircraft.mzfw if not flight.entranceExam else None
 
     def getWeight(self, state):
@@ -829,5 +831,6 @@
     def isCondition(self, flight, aircraft, oldState, state):
         """Check if the fault condition holds."""
-        return flight.stage==const.STAGE_PUSHANDTAXI and \
+        return not flight.entranceExam and \
+               flight.stage==const.STAGE_PUSHANDTAXI and \
                PayloadChecker.isZFWFaulty(state.zfw, flight.zfw)
                
Index: src/mlx/flight.py
===================================================================
--- src/mlx/flight.py	(revision 183)
+++ src/mlx/flight.py	(revision 184)
@@ -29,5 +29,4 @@
 
         self.flareTimeFromFS = False
-        self.entranceExam = False
 
         self.aircraftType = None
@@ -67,4 +66,9 @@
         """Get the flight stage."""
         return self._stage
+
+    @property
+    def entranceExam(self):
+        """Get whether an entrance exam is being performed."""
+        return self._gui.entranceExam
 
     @property
Index: src/mlx/gui/checklist.py
===================================================================
--- src/mlx/gui/checklist.py	(revision 175)
+++ src/mlx/gui/checklist.py	(revision 184)
@@ -72,5 +72,5 @@
             
         filter = gtk.FileFilter()
-        filter.set_name(xstr("chklst_filter_all"))
+        filter.set_name(xstr("file_filter_all"))
         filter.add_pattern("*.*")
         self._fileChooser.add_filter(filter)
Index: src/mlx/gui/flight.py
===================================================================
--- src/mlx/gui/flight.py	(revision 170)
+++ src/mlx/gui/flight.py	(revision 184)
@@ -11,4 +11,5 @@
 from mlx.i18n import xstr
 from mlx.sound import startSound
+import mlx.web as web
 
 import datetime
@@ -215,5 +216,5 @@
                                   xscale = 0.0, yscale = 0.0)
 
-        table = gtk.Table(2, 3)
+        table = gtk.Table(4, 2)
         table.set_row_spacings(4)
         table.set_col_spacings(32)
@@ -229,5 +230,5 @@
 
         self._pilotID = gtk.Entry()
-        self._pilotID.connect("changed", self._setLoginButton)
+        self._pilotID.connect("changed", self._setControls)
         self._pilotID.set_tooltip_text(xstr("login_pilotID_tooltip"))
         table.attach(self._pilotID, 1, 2, 0, 1)
@@ -243,5 +244,5 @@
         self._password = gtk.Entry()
         self._password.set_visibility(False)
-        self._password.connect("changed", self._setLoginButton)
+        self._password.connect("changed", self._setControls)
         self._password.set_tooltip_text(xstr("login_password_tooltip"))
         table.attach(self._password, 1, 2, 1, 2)
@@ -253,8 +254,20 @@
         table.attach(self._rememberButton, 1, 2, 2, 3, ypadding = 8)
 
+        self._entranceExam = gtk.CheckButton(xstr("login_entranceExam"))
+        self._entranceExam.set_use_underline(True)
+        self._entranceExam.set_tooltip_text(xstr("login_entranceExam_tooltip"))
+        self._entranceExam.connect("toggled", self._setControls)
+        table.attach(self._entranceExam, 1, 2, 3, 4, ypadding = 12)
+
         self._loginButton = self.addButton(xstr("button_login"), default = True)
-        self._loginButton.set_sensitive(False)
         self._loginButton.connect("clicked", self._loginClicked)
-        self._loginButton.set_tooltip_text(xstr("login_button_tooltip"))        
+        self._loginButton.set_tooltip_text(xstr("login_button_tooltip"))
+
+
+    @property
+    def entranceExam(self):
+        """Get whether an entrance exam is being performed."""
+        return self._entranceExam.get_active() and \
+               self._pilotID.get_text()!=""
 
     def activate(self):
@@ -264,21 +277,37 @@
         self._password.set_text(config.password)
         self._rememberButton.set_active(config.rememberPassword)
-
-    def _setLoginButton(self, entry):
-        """Set the login button's sensitivity.
-
-        The button is sensitive only if both the pilot ID and the password
-        fields contain values."""
-        self._loginButton.set_sensitive(self._pilotID.get_text()!="" and
-                                        self._password.get_text()!="")
+        self._setControls(None)    
+
+    def _setControls(self, entry = None):
+        """Set the sensitivity of the various controls.
+
+        The login button is sensitive only if both the pilot ID and the
+        password fields contain values.
+
+        The password field is sensitive only, if the entrance exam checkbox is
+        not selected.
+
+        The remember password checkbox is sensitive only, if the password field
+        contains text.
+
+        The entrance exam checkbox is senstive only, if the pilot ID is not
+        empty."""
+        pilotID = self._pilotID.get_text()
+        password = self._password.get_text()
+        entranceExam = self._entranceExam.get_active()
+        self._password.set_sensitive(not entranceExam)
+        self._rememberButton.set_sensitive(password!="" and not entranceExam)
+        self._entranceExam.set_sensitive(pilotID!="")
+        self._loginButton.set_sensitive(pilotID!="" and
+                                        (password!="" or entranceExam))
 
     def _loginClicked(self, button):
         """Called when the login button was clicked."""
-        self._loginButton.set_sensitive(False)
         gui = self._wizard.gui
         gui.beginBusy(xstr("login_busy"))
         gui.webHandler.login(self._loginResultCallback,
-                            self._pilotID.get_text(),
-                            self._password.get_text())
+                             self._pilotID.get_text(),
+                             self._password.get_text(),
+                             entranceExam = self.entranceExam)
 
     def _loginResultCallback(self, returned, result):
@@ -306,10 +335,16 @@
                 self._wizard.nextPage()
             else:
+                message = xstr("login_entranceExam_invalid"
+                               if self.entranceExam else
+                               xstr("login_invalid"))
                 dialog = gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
                                            type = MESSAGETYPE_ERROR,
-                                           message_format = xstr("login_invalid"))
+                                           message_format = message)
                 dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
                 dialog.set_title(WINDOW_TITLE_BASE)
-                dialog.format_secondary_markup(xstr("login_invalid_sec"))
+                secondary = xstr("login_entranceExam_invalid_sec"
+                                 if self.entranceExam else
+                                 xstr("login_invalid_sec"))
+                dialog.format_secondary_markup(secondary)
                 dialog.run()
                 dialog.hide()
@@ -375,25 +410,67 @@
         self.setMainWidget(alignment)
 
+        self._loadButton = self.addButton(xstr("flightsel_load"),
+                                          sensitive = True,
+                                          tooltip = xstr("flightsel_load_tooltip"))
+        self._loadButton.connect("clicked", self._loadButtonClicked)
+        self._loadDialog = None
+        
         self._button = self.addNextButton(sensitive = False,
                                           clicked =  self._forwardClicked)
+
+        self._flights = []
 
     def activate(self):
         """Fill the flight list."""
         self._flightList.set_sensitive(True)
+        self._flights = []
         self._listStore.clear()
         for flight in self._wizard.loginResult.flights:
-            self._listStore.append([str(flight.departureTime),
-                                    flight.callsign,
-                                    flight.departureICAO,
-                                    flight.arrivalICAO])
-
+            self._addFlight(flight)
+            
     def finalize(self):
         """Finalize the page."""
         self._flightList.set_sensitive(False)
 
+    def _addFlight(self, flight):
+        """Add the given file to the list of flights."""
+        self._flights.append(flight)
+        self._listStore.append([str(flight.departureTime),
+                                flight.callsign,
+                                flight.departureICAO,
+                                flight.arrivalICAO])
+
     def _selectionChanged(self, selection):
         """Called when the selection is changed."""
         self._button.set_sensitive(selection.count_selected_rows()==1)
 
+    def _loadButtonClicked(self, loadButton):
+        """Called when the load a flight button is clicked."""
+        dialog = self._getLoadDialog()
+        dialog.show_all()
+        response = dialog.run()
+        dialog.hide()
+
+        if response==RESPONSETYPE_OK:
+            fileName = dialog.get_filename()
+            print "Loading", fileName
+            bookedFlight = web.BookedFlight()
+            try:
+                with open(fileName, "rt") as f:
+                    bookedFlight.readFromFile(f)
+                self._addFlight(bookedFlight)                
+            except Exception, e:
+                print "Failed to load flight:", str(e)
+                dialog = gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
+                                           type = MESSAGETYPE_ERROR,
+                                           message_format =
+                                           xstr("flightsel_load_failed"))
+                dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
+                dialog.set_title(WINDOW_TITLE_BASE)
+                secondary = xstr("flightsel_load_failed_sec")
+                dialog.format_secondary_markup(secondary)
+                dialog.run()
+                dialog.hide()                
+            
     def _forwardClicked(self, button):
         """Called when the forward button was clicked."""
@@ -406,5 +483,5 @@
             [index] = path.get_indices() if pygobject else path
 
-            flight = self._wizard.loginResult.flights[index]
+            flight = self._flights[index]
             self._wizard._bookedFlight = flight
             self._wizard.gui.enableFlightInfo()
@@ -415,5 +492,6 @@
         """Update the departure gate for the booked flight."""
         flight = self._wizard._bookedFlight
-        if self._wizard.gui.config.onlineGateSystem:
+        if self._wizard.gui.config.onlineGateSystem and \
+           not self._wizard.entranceExam:
             if flight.departureICAO=="LHBP":
                 self._wizard.getFleet(self._fleetRetrieved)
@@ -449,5 +527,34 @@
         self._nextDistance = 2
         self._wizard.jumpPage(2)
-        
+
+    def _getLoadDialog(self):
+        """Get the dialog to load a flight file."""
+        if self._loadDialog is not None:
+            return self._loadDialog
+        
+        gui = self._wizard.gui
+        dialog = gtk.FileChooserDialog(title = WINDOW_TITLE_BASE + " - " +
+                                       xstr("flightsel_load_title"),
+                                       action = FILE_CHOOSER_ACTION_OPEN,
+                                       buttons = (gtk.STOCK_CANCEL,
+                                                  RESPONSETYPE_CANCEL,
+                                                  gtk.STOCK_OK, RESPONSETYPE_OK),
+                                       parent = gui.mainWindow)
+        dialog.set_modal(True)            
+
+        filter = gtk.FileFilter()
+        filter.set_name(xstr("flightsel_filter_flights"))
+        filter.add_pattern("*.vaflight")
+        dialog.add_filter(filter)
+            
+        filter = gtk.FileFilter()
+        filter.set_name(xstr("file_filter_all"))
+        filter.add_pattern("*.*")
+        dialog.add_filter(filter)
+
+        self._loadDialog = dialog
+        
+        return dialog        
+    
 #-----------------------------------------------------------------------------
 
@@ -2036,5 +2143,6 @@
         if self._wizard.gui.config.onlineGateSystem and \
            not self._completed and \
-           self._wizard.bookedFlight.arrivalICAO=="LHBP":
+           self._wizard.bookedFlight.arrivalICAO=="LHBP" and \
+           not self._wizard.entranceExam:
             self._wizard.getFleet(callback = self._fleetRetrieved,
                                   force = True)
@@ -2238,5 +2346,6 @@
         self._gatesModel.clear()
         if self._wizard.gui.config.onlineGateSystem and \
-           self._wizard.bookedFlight.arrivalICAO=="LHBP":
+           self._wizard.bookedFlight.arrivalICAO=="LHBP" and \
+           not self._wizard.entranceExam:
             occupiedGates = self._wizard._fleet.getOccupiedGateNumbers()
             for gateNumber in const.lhbpGateNumbers:
@@ -2261,5 +2370,6 @@
         
         self._saveButton.set_sensitive(sensitive)
-        self._sendButton.set_sensitive(sensitive)        
+        self._sendButton.set_sensitive(sensitive and
+                                       self._wizard.bookedFlight.id is not None)
 
     def _flightTypeChanged(self, comboBox):
@@ -2339,10 +2449,10 @@
             
             filter = gtk.FileFilter()
-            filter.set_name(xstr("loadPIREP_filter_pireps"))
+            filter.set_name(xstr("file_filter_pireps"))
             filter.add_pattern("*.pirep")
             dialog.add_filter(filter)
             
             filter = gtk.FileFilter()
-            filter.set_name(xstr("loadPIREP_filter_all"))
+            filter.set_name(xstr("file_filter_all"))
             filter.add_pattern("*.*")
             dialog.add_filter(filter)
@@ -2361,5 +2471,7 @@
     def _handlePIREPSent(self, returned, result):
         """Callback for the PIREP sending result."""
-        if self._wizard.gui.config.onlineGateSystem and returned and result.success:
+        if self._wizard.gui.config.onlineGateSystem and \
+           not self._wizard.entranceExam and \
+           returned and result.success:
             bookedFlight = self._wizard.bookedFlight
             if bookedFlight.arrivalICAO=="LHBP":
@@ -2394,6 +2506,7 @@
         self._pages = []
         self._currentPage = None
-        
-        self._pages.append(LoginPage(self))
+
+        self._loginPage = LoginPage(self)
+        self._pages.append(self._loginPage)
         self._pages.append(FlightSelectionPage(self))
         self._pages.append(GateSelectionPage(self))
@@ -2432,4 +2545,9 @@
 
         self._initialize()
+
+    @property
+    def entranceExam(self):
+        """Get whether an entrance exam is about to be taken."""
+        return self._loginPage.entranceExam
         
     @property
Index: src/mlx/gui/gui.py
===================================================================
--- src/mlx/gui/gui.py	(revision 182)
+++ src/mlx/gui/gui.py	(revision 184)
@@ -179,4 +179,9 @@
         return self._flight
 
+    @property
+    def entranceExam(self):
+        """Get whether an entrance exam is about to be taken."""
+        return self._wizard.entranceExam
+        
     @property
     def loginResult(self):
@@ -977,10 +982,10 @@
 
             filter = gtk.FileFilter()
-            filter.set_name(xstr("loadPIREP_filter_pireps"))
+            filter.set_name(xstr("file_filter_pireps"))
             filter.add_pattern("*.pirep")
             dialog.add_filter(filter)
             
             filter = gtk.FileFilter()
-            filter.set_name(xstr("loadPIREP_filter_all"))
+            filter.set_name(xstr("file_filter_all"))
             filter.add_pattern("*.*")
             dialog.add_filter(filter)
Index: src/mlx/i18n.py
===================================================================
--- src/mlx/i18n.py	(revision 183)
+++ src/mlx/i18n.py	(revision 184)
@@ -147,4 +147,7 @@
         self.add("aircraft_t154", "Tupolev Tu-154")
         self.add("aircraft_yk40", "Yakovlev Yak-40")
+
+        self.add("file_filter_all", "All files")
+        self.add("file_filter_pireps", "PIREP files")
 
         self.add("button_ok", "_OK")
@@ -221,10 +224,18 @@
                  "is stored as text, and anybody who can access your files will "
                  "be able to read it.")
+        self.add("login_entranceExam", "_Entrance Exam")
+        self.add("login_entranceExam_tooltip",
+                 "Check this to log in to take your entrance exam.")
         self.add("button_login", "Logi_n")
         self.add("login_button_tooltip", "Click to log in.")
         self.add("login_busy", "Logging in...")
         self.add("login_invalid", "Invalid pilot's ID or password.")
+        self.add("login_entranceExam_invalid",
+                 "Invalid pilot's ID or not registered for exam.")
         self.add("login_invalid_sec",
                  "Check the ID and try to reenter the password.")
+        self.add("login_entranceExam_invalid_sec",
+                 "Check the ID and make sure that you are "
+                 "allowed to take your entrance exam.")
         self.add("login_failconn",
                  "Failed to connect to the MAVA website.")
@@ -243,4 +254,14 @@
         self.add("flightsel_from", "From")
         self.add("flightsel_to", "To")
+        self.add("flightsel_load", "Load flight from _file")
+        self.add("flightsel_load_tooltip",
+                 "Click here to load a flight from a file, "
+                 "and add it to the list above.")
+        self.add("flightsel_load_title", "Load flight from file")
+        self.add("flightsel_filter_flights", "Flight files")
+        self.add("flightsel_load_failed",
+                 "Could not load the flight file")
+        self.add("flightsel_load_failed_sec",
+                 "Check the debug log for more details.")
 
         self.add("fleet_busy", "Retrieving fleet...")
@@ -665,5 +686,4 @@
                  "Move down the selected file(s) in the checklist.")
         self.add("chklst_filter_audio", "Audio files")
-        self.add("chklst_filter_all", "All files")
         self.add("chklst_header", "Checklist files")
 
@@ -758,6 +778,4 @@
 
         self.add("loadPIREP_browser_title", "Select the PIREP to load")
-        self.add("loadPIREP_filter_pireps", "PIREP files")
-        self.add("loadPIREP_filter_all", "All files")
         self.add("loadPIREP_failed", "Failed to load the PIREP")
         self.add("loadPIREP_failed_sec", "See the debug log for the details.")
@@ -821,4 +839,7 @@
         self.add("aircraft_t154", "Tupoljev Tu-154")
         self.add("aircraft_yk40", "Jakovlev Jak-40")
+
+        self.add("file_filter_all", "Összes fájl")
+        self.add("file_filter_pireps", "PIREP fájlok")
 
         self.add("button_ok", "_OK")
@@ -1286,5 +1307,4 @@
                  "Az ellenőrzőlistából kijelölt fájl(ok) eggyel lejjebb mozgatása.")
         self.add("chklst_filter_audio", "Audio fájlok")
-        self.add("chklst_filter_all", "Összes fájl")
         self.add("chklst_header", "Ellenőrzőlista fájljai")
 
@@ -1446,6 +1466,4 @@
 
         self.add("loadPIREP_browser_title", "Válaszd ki a betöltendő PIREP-et")
-        self.add("loadPIREP_filter_pireps", "PIREP fájlok")
-        self.add("loadPIREP_filter_all", "Összes fájl")
         self.add("loadPIREP_failed", "Nem tudtam betölteni a PIREP-et")
         self.add("loadPIREP_failed_sec",
Index: src/mlx/web.py
===================================================================
--- src/mlx/web.py	(revision 151)
+++ src/mlx/web.py	(revision 184)
@@ -65,11 +65,18 @@
                       const.AIRCRAFT_T154 : "TU5",
                       const.AIRCRAFT_YK40 : "YK4" }
-    
-    def __init__(self, id, f):
-        """Construct a booked flight with the given ID.
-
-        The rest of the data is read from the given file."""
-
+
+    @staticmethod
+    def getDateTime(date, time):
+        """Get a datetime object from the given textual date and time."""
+        return datetime.datetime.strptime(date + " " + time,
+                                          "%Y-%m-%d %H:%M:%S")
+
+    def __init__(self, id = None):
+        """Construct a booked flight with the given ID."""
         self.id = id
+
+    def readFromWeb(self, f):
+        """Read the data of the flight from the web via the given file
+        object."""
         self.callsign = readline(f)
 
@@ -89,20 +96,90 @@
 
         departureTime = readline(f)
-        self.departureTime = datetime.datetime.strptime(date + " " + departureTime,
-                                                        "%Y-%m-%d %H:%M:%S")
+        self.departureTime = BookedFlight.getDateTime(date, departureTime)
                                                
         arrivalTime = readline(f)
-        self.arrivalTime = datetime.datetime.strptime(date + " " + arrivalTime,
-                                                      "%Y-%m-%d %H:%M:%S")
+        self.arrivalTime = BookedFlight.getDateTime(date, arrivalTime)
 
         if not readline(f)==".NEXT.":
             raise Exception("Invalid line in flight data")
 
+    def readFromFile(self, f):
+        """Read the data of the flight from a file via the given file
+        object."""
+        date = None
+        departureTime = None
+        arrivalTime = None
+        
+        line = f.readline()
+        lineNumber = 0    
+        while line:
+            lineNumber += 1
+            line = line.strip()
+            
+            hashIndex = line.find("#")
+            if hashIndex>=0: line = line[:hashIndex]
+            if line:
+                equalIndex = line.find("=")
+                lineOK = equalIndex>0
+                
+                if lineOK:
+                    key = line[:equalIndex].strip()                    
+                    value = line[equalIndex+1:].strip().replace("\:", ":")
+                    
+                    lineOK = key and value
+
+                if lineOK:
+                    if key=="callsign": self.callsign = value
+                    elif key=="date": date = value
+                    elif key=="dep_airport": self.departureICAO = value
+                    elif key=="dest_airport": self.arrivalICAO = value
+                    elif key=="planecode": self.aircraftType = \
+                         self._decodeAircraftType(value)
+                    elif key=="tail_nr": self.tailNumber = value
+                    elif key=="passenger": self.numPassengers = int(value)
+                    elif key=="crew": self.numCrew = int(value)
+                    elif key=="bag": self.bagWeight = int(value)
+                    elif key=="cargo": self.cargoWeight = int(value)
+                    elif key=="mail": self.mailWeight = int(value)
+                    elif key=="flight_route": self.route = value
+                    elif key=="departure_time": departureTime = value
+                    elif key=="arrival_time": arrivalTime = value
+                    elif key=="foglalas_id": pass
+                    elif key=="planetype": pass
+                    else: lineOK = False
+
+                if not lineOK:
+                    print "web.BookedFlight.readFromFile: line %d is invalid" % \
+                          (lineNumber,)
+
+            line = f.readline()
+
+        if date is not None:
+            if departureTime is not None:
+                self.departureTime = BookedFlight.getDateTime(date,
+                                                              departureTime)
+            if arrivalTime is not None:
+                self.arrivalTime = BookedFlight.getDateTime(date,
+                                                            arrivalTime)
+
+        d = dir(self)
+        for attribute in ["callsign", "departureICAO", "arrivalICAO",
+                          "aircraftType", "tailNumber",
+                          "numPassengers", "numCrew",
+                          "bagWeight", "cargoWeight", "mailWeight",
+                          "route", "departureTime", "arrivalTime"]:
+            if attribute not in d:
+                raise Exception("Attribute %s could not be read" % (attribute,))
+            
     def _readAircraftType(self, f):
         """Read the aircraft type from the given file."""
         line = readline(f)
         typeCode = line[:3]
+        self.aircraftType = self._decodeAircraftType(typeCode)
+
+    def _decodeAircraftType(self, typeCode):
+        """Decode the aircraft type from the given typeCode."""
         if typeCode in self.TYPECODE2TYPE:
-            self.aircraftType = self.TYPECODE2TYPE[typeCode]
+            return self.TYPECODE2TYPE[typeCode]
         else:
             raise Exception("Invalid aircraft type code: '" + typeCode + "'")
@@ -346,5 +423,5 @@
     iso88592decoder = codecs.getdecoder("iso-8859-2")
     
-    def __init__(self, callback, pilotID, password):
+    def __init__(self, callback, pilotID, password, entranceExam):
         """Construct the login request with the given pilot ID and
         password."""
@@ -353,4 +430,5 @@
         self._pilotID = pilotID
         self._password = password
+        self._entranceExam = entranceExam
 
     def run(self):
@@ -364,26 +442,42 @@
         password = md5.hexdigest()
 
-        url = "http://www.virtualairlines.hu/leker2.php?pid=%s&psw=%s" % \
-              (pilotID, password)
+        if self._entranceExam:
+            url = "http://www.virtualairlines.hu/ellenorzo/getflightplan.php?pid=%s" % \
+                  (pilotID,)
+        else:
+            url = "http://www.virtualairlines.hu/leker2.php?pid=%s&psw=%s" % \
+                  (pilotID, password)
 
         result = Result()
+        result.entranceExam = self._entranceExam
 
         f = urllib2.urlopen(url, timeout = 10.0)
 
         status = readline(f)
-        result.loggedIn = status == ".OK."
+        if self._entranceExam:
+            result.loggedIn = status != "#NOEXAM"
+        else:
+            result.loggedIn = status == ".OK."
 
         if result.loggedIn:
             result.pilotID = self._pilotID
-            result.pilotName = self.iso88592decoder(readline(f))[0]
-            result.exams = readline(f)
             result.flights = []
-
-            while True:
-                line = readline(f)
-                if not line or line == "#ENDPIREP": break
-
-                flight = BookedFlight(line, f)
-                result.flights.append(flight)
+            # FIXME: this may not be the correct behaviour
+            # for an entrance exam, but the website returns
+            # an error
+            if self._entranceExam:
+                result.pilotName = result.pilotID
+                result.exams = ""
+            else:
+                result.pilotName = self.iso88592decoder(readline(f))[0]
+                result.exams = readline(f)
+                
+                while True:
+                    line = readline(f)
+                    if not line or line == "#ENDPIREP": break
+
+                    flight = BookedFlight(line)
+                    flight.readFromWeb(f)
+                    result.flights.append(flight)
 
             result.flights.sort(cmp = lambda flight1, flight2:
@@ -740,7 +834,7 @@
         self.daemon = True
 
-    def login(self, callback, pilotID, password):
+    def login(self, callback, pilotID, password, entranceExam = False):
         """Enqueue a login request."""
-        self._addRequest(Login(callback, pilotID, password))
+        self._addRequest(Login(callback, pilotID, password, entranceExam))
 
     def getFleet(self, callback):
