Index: src/mlx/acars.py
===================================================================
--- src/mlx/acars.py	(revision 139)
+++ src/mlx/acars.py	(revision 139)
@@ -0,0 +1,45 @@
+# Module for ACARS handling
+
+#------------------------------------------------------------------------------
+
+import const
+
+#------------------------------------------------------------------------------
+
+class ACARS(object):
+    """The ACARS object."""
+    def __init__(self, gui, state):
+        """Construct the acars."""
+        self.pid = gui.config.pilotID
+        self.pilotName = gui.loginResult.pilotName
+
+        flight = gui.flight
+        aircraft = flight.aircraft
+
+        self.state = state
+        self.bookedFlight = gui.bookedFlight
+        
+        self.blockTime = 0 if flight.blockTimeStart is None \
+                         else aircraft.state.timestamp - flight.blockTimeStart
+        self.stage = flight.stage
+
+    def getBlockTimeText(self):
+        """Get the block time in HH:MM format"""
+        hours = int(self.blockTime / 3600)
+        minutes = int((self.blockTime / 60)) % 60
+        return "%02d:%02d" % (hours, minutes)
+
+    def getEventText(self):
+        """Get the 'event', i.e. the stage."""
+        if self.stage==const.STAGE_BOARDING: return "Boarding"
+        elif self.stage==const.STAGE_PUSHANDTAXI: return "Taxiing"
+        elif self.stage==const.STAGE_TAKEOFF: return "Departing"
+        elif self.stage==const.STAGE_CLIMB: return "Climbing"
+        elif self.stage==const.STAGE_CRUISE: return "Cruising"
+        elif self.stage==const.STAGE_DESCENT:
+            return "Descending" if self.state.altitude>=10000 \
+                   else "Approaching"
+        else:
+            return "Landed"
+        
+#------------------------------------------------------------------------------
Index: src/mlx/acft.py
===================================================================
--- src/mlx/acft.py	(revision 136)
+++ src/mlx/acft.py	(revision 139)
@@ -8,5 +8,7 @@
 import util
 
+import sys
 import time
+import traceback
 
 #---------------------------------------------------------------------------------------
@@ -59,4 +61,12 @@
             self._checkers.append(checks.VisibilityChecker())
 
+        # FIXME: we should have a central data model object, and not collect
+        # the data from the GUI. However, some pieces of data (e.g. V-speeds,
+        # etc. that is entered into the GUI) *should* be a part of the GUI and
+        # 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:
+            self._checkers.append(checks.ACARSSender(flight._gui))
+
         # Fault checkers
         
@@ -105,4 +115,9 @@
         return self._flight.logger
 
+    @property
+    def state(self):
+        """Get the current aircraft state."""
+        return self._aircraftState
+    
     def getFlapsSpeedLimit(self, flaps):
         """Get the speed limit for the given flaps setting."""
@@ -119,6 +134,10 @@
         """Called when the state of the aircraft changes."""
         for checker in self._checkers:
-            checker.check(self._flight, self, self._flight.logger,
-                          self._aircraftState, aircraftState)
+            try:
+                checker.check(self._flight, self, self._flight.logger,
+                              self._aircraftState, aircraftState)
+            except:
+                print >> sys.stderr, "Checker", checker, "failed"
+                traceback.print_exc()
 
         self._flight.handleState(self._aircraftState, aircraftState)
Index: src/mlx/checks.py
===================================================================
--- src/mlx/checks.py	(revision 134)
+++ src/mlx/checks.py	(revision 139)
@@ -6,4 +6,7 @@
 import const
 import util
+from acars import ACARS
+
+import time
 
 #---------------------------------------------------------------------------------------
@@ -85,4 +88,39 @@
 #---------------------------------------------------------------------------------------
 
+class ACARSSender(StateChecker):
+    """Sender of online ACARS.
+
+    It sends the ACARS every 3 minutes to the MAVA website."""
+
+    # The interval at which ACARS is sent
+    INTERVAL = 3*60.0
+    
+    def __init__(self, gui):
+        """Construct the ACARS sender."""
+        self._gui = gui
+        self._lastSent = None
+
+    def check(self, flight, aircraft, logger, oldState, state):
+        """If the time has come to send the ACARS, send it."""
+        now = time.time()
+        
+        if self._lastSent is not None and \
+           (self._lastSent + ACARSSender.INTERVAL)>now:
+            return 
+
+        acars = ACARS(self._gui, state)
+        self._gui.webHandler.sendACARS(self._acarsCallback, acars)
+
+    def _acarsCallback(self, returned, result):
+        """Callback for ACARS sending."""
+        if returned:
+            print "Sent online ACARS"
+            self._lastSent = time.time() if self._lastSent is None \
+                             else self._lastSent + ACARSSender.INTERVAL
+        else:
+            print "Failed to send the ACARS"
+        
+#---------------------------------------------------------------------------------------
+
 class TakeOffLogger(StateChecker):
     """Logger for the cruise speed."""
Index: src/mlx/config.py
===================================================================
--- src/mlx/config.py	(revision 136)
+++ src/mlx/config.py	(revision 139)
@@ -38,4 +38,5 @@
         self._language = ""
         self._onlineGateSystem = True
+        self._onlineACARS = True
         self._flareTimeFromFS = False
         
@@ -105,4 +106,16 @@
         if onlineGateSystem!=self._onlineGateSystem:
             self._onlineGateSystem = onlineGateSystem
+            self._modified = True
+
+    @property
+    def onlineACARS(self):
+        """Get whether the online ACARS system should be used."""
+        return self._onlineACARS
+
+    @onlineACARS.setter
+    def onlineACARS(self, onlineACARS):
+        """Set whether the online ACARS system should be used."""
+        if onlineACARS!=self._onlineACARS:
+            self._onlineACARS = onlineACARS
             self._modified = True
 
@@ -179,4 +192,6 @@
                                                   "onlineGateSystem",
                                                   True)
+        self._onlineACARS = self._getBoolean(config, "general",
+                                             "onlineACARS", True)
         self._flareTimeFromFS = self._getBoolean(config, "general",
                                                  "flareTimeFromFS",
@@ -212,4 +227,6 @@
         config.set("general", "onlineGateSystem",
                    "yes" if self._onlineGateSystem else "no")
+        config.set("general", "onlineACARS",
+                   "yes" if self._onlineACARS else "no")
         config.set("general", "flareTimeFromFS",
                    "yes" if self._flareTimeFromFS else "no")
Index: src/mlx/gui/flight.py
===================================================================
--- src/mlx/gui/flight.py	(revision 138)
+++ src/mlx/gui/flight.py	(revision 139)
@@ -212,5 +212,5 @@
         alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
-        
+
         table = gtk.Table(2, 3)
         table.set_row_spacings(4)
Index: src/mlx/gui/gui.py
===================================================================
--- src/mlx/gui/gui.py	(revision 135)
+++ src/mlx/gui/gui.py	(revision 139)
@@ -165,4 +165,9 @@
         """Get the flight being performed."""
         return self._flight
+
+    @property
+    def loginResult(self):
+        """Get the result of the login."""
+        return self._wizard.loginResult
 
     @property
Index: src/mlx/gui/prefs.py
===================================================================
--- src/mlx/gui/prefs.py	(revision 136)
+++ src/mlx/gui/prefs.py	(revision 139)
@@ -68,4 +68,5 @@
         self._setLanguage(config.language)
         self._onlineGateSystem.set_active(config.onlineGateSystem)
+        self._onlineACARS.set_active(config.onlineACARS)
         self._flareTimeFromFS.set_active(config.flareTimeFromFS)
 
@@ -91,4 +92,5 @@
         config.language = self._getLanguage()
         config.onlineGateSystem = self._onlineGateSystem.get_active()
+        config.onlineACARS = self._onlineACARS.get_active()
         config.flareTimeFromFS = self._flareTimeFromFS.get_active()
 
@@ -148,4 +150,9 @@
         self._onlineGateSystem.set_tooltip_text(xstr("prefs_onlineGateSystem_tooltip"))
         mainBox.pack_start(self._onlineGateSystem, False, False, 4)
+
+        self._onlineACARS = gtk.CheckButton(xstr("prefs_onlineACARS"))
+        self._onlineACARS.set_use_underline(True)
+        self._onlineACARS.set_tooltip_text(xstr("prefs_onlineACARS_tooltip"))
+        mainBox.pack_start(self._onlineACARS, False, False, 4)
 
         self._flareTimeFromFS = gtk.CheckButton(xstr("prefs_flaretimeFromFS"))
Index: src/mlx/i18n.py
===================================================================
--- src/mlx/i18n.py	(revision 136)
+++ src/mlx/i18n.py	(revision 139)
@@ -565,4 +565,9 @@
                  "If this is checked, the logger will query and update the "
                  "LHBP Online Gate System.")
+        self.add("prefs_onlineACARS",
+                 "Use the Online ACA_RS System")
+        self.add("prefs_onlineACARS_tooltip",
+                 "If this is checked, the logger will continuously update "
+                 "the MAVA Online ACARS System with your flight's data.")
         self.add("prefs_flaretimeFromFS",
                  "Take flare _time from the simulator")
@@ -1065,4 +1070,9 @@
                  "Ha ezt bejelölöd, a logger lekérdezi és frissíti az "
                  "LHBP Online Gate System adatait.")
+        self.add("prefs_onlineACARS",
+                 "Az Online ACA_RS rendszer használata")
+        self.add("prefs_onlineACARS_tooltip",
+                 "Ha ezt bejölöd, a logger folyamatosan közli a repülésed "
+                 "adatait a MAVA Online ACARS rendszerrel.")
         self.add("prefs_flaretimeFromFS",
                  "A ki_lebegtetés idejét vedd a szimulátorból")
Index: src/mlx/web.py
===================================================================
--- src/mlx/web.py	(revision 130)
+++ src/mlx/web.py	(revision 139)
@@ -50,4 +50,20 @@
                       "YK4" : const.AIRCRAFT_YK40 }
 
+    TYPE2TYPECODE = { const.AIRCRAFT_B736 : "736",
+                      const.AIRCRAFT_B737 : "73G",
+                      const.AIRCRAFT_B738 : "738",
+                      const.AIRCRAFT_B733 : "733",
+                      const.AIRCRAFT_B734 : "734",
+                      const.AIRCRAFT_B735 : "735",
+                      const.AIRCRAFT_DH8D : "DH4",
+                      const.AIRCRAFT_B762 : "762",
+                      const.AIRCRAFT_B763 : "763",
+                      const.AIRCRAFT_CRJ2 : "CR2",
+                      const.AIRCRAFT_F70  : "F70",
+                      const.AIRCRAFT_DC3  : "LI2",
+                      const.AIRCRAFT_T134 : "TU3",
+                      const.AIRCRAFT_T154 : "TU5",
+                      const.AIRCRAFT_YK40 : "YK4" }
+    
     def __init__(self, id, f):
         """Construct a booked flight with the given ID.
@@ -581,4 +597,132 @@
 #------------------------------------------------------------------------------
 
+class SendPIREP(Request):
+    """A request to send a PIREP to the MAVA website."""
+    _flightTypes = { const.FLIGHTTYPE_SCHEDULED : "SCHEDULED",
+                     const.FLIGHTTYPE_OLDTIMER : "OT",
+                     const.FLIGHTTYPE_VIP : "VIP",
+                     const.FLIGHTTYPE_CHARTER : "CHARTER" }
+
+    _latin2Encoder = codecs.getencoder("iso-8859-2")
+
+    def __init__(self, callback, pirep):
+        """Construct the request for the given PIREP."""
+        super(SendPIREP, self).__init__(callback)
+        self._pirep = pirep
+
+    def run(self):
+        """Perform the sending of the PIREP."""
+        url = "http://www.virtualairlines.hu/malevacars.php"
+
+        pirep = self._pirep
+
+        data = {}
+        data["acarsdata"] = pirep.getACARSText()
+
+        bookedFlight = pirep.bookedFlight
+        data["foglalas_id"] = bookedFlight.id
+        data["repdate"] = bookedFlight.departureTime.date().strftime("%Y-%m-%d")
+        data["fltnum"] = bookedFlight.callsign
+        data["depap"] = bookedFlight.departureICAO
+        data["arrap"] = bookedFlight.arrivalICAO
+        data["pass"] = str(bookedFlight.numPassengers)
+        data["crew"] = str(bookedFlight.numCrew)
+        data["cargo"] = str(pirep.cargoWeight)
+        data["bag"] = str(bookedFlight.bagWeight)
+        data["mail"] = str(bookedFlight.mailWeight)
+        
+        data["flttype"] = SendPIREP._flightTypes[pirep.flightType]
+        data["onoff"] = "1" if pirep.online else "0"
+        data["bt_dep"] = util.getTimestampString(pirep.blockTimeStart)
+        data["bt_arr"] = util.getTimestampString(pirep.blockTimeEnd)
+        data["bt_dur"] = util.getTimeIntervalString(pirep.blockTimeEnd -
+                                                    pirep.blockTimeStart)
+        data["ft_dep"] = util.getTimestampString(pirep.flightTimeStart)
+        data["ft_arr"] = util.getTimestampString(pirep.flightTimeEnd)
+        data["ft_dur"] = util.getTimeIntervalString(pirep.flightTimeEnd -
+                                                    pirep.flightTimeStart)
+        data["timecomm"] = pirep.getTimeComment()
+        data["fuel"] = "%.0f" % (pirep.fuelUsed,)
+        data["dep_rwy"] = pirep.departureRunway
+        data["arr_rwy"] = pirep.arrivalRunway
+        data["wea_dep"] = pirep.departureMETAR
+        data["wea_arr"] = pirep.arrivalMETAR
+        data["alt"] = "FL%.0f" % (pirep.filedCruiseAltitude/100.0,)
+        if pirep.filedCruiseAltitude!=pirep.cruiseAltitude:
+            data["mod_alt"] = "FL%.0f" % (pirep.cruiseAltitude/100.0,)
+        else:
+            data["mod_alt"] = ""
+        data["sid"] = pirep.sid
+        data["navroute"] = pirep.route
+        data["star"] = pirep.getSTAR()
+        data["aprtype"] = pirep.approachType
+        data["diff"] = "2"
+        data["comment"] = SendPIREP._latin2Encoder(pirep.comments)[0]
+        data["flightdefect"] = SendPIREP._latin2Encoder(pirep.flightDefects)[0]
+        data["kritika"] = pirep.getRatingText()
+        data["flightrating"] = "%.1f" % (max(0.0, pirep.rating),)
+        data["distance"] = "%.3f" % (pirep.flownDistance,)
+        data["insdate"] = datetime.date.today().strftime("%Y-%m-%d")
+
+        f = urllib2.urlopen(url, urllib.urlencode(data), timeout = 10.0)
+        try:
+            result = Result()
+            line = f.readline().strip()
+            print "PIREP result from website:", line
+            result.success = line=="OK"
+            result.alreadyFlown = line=="MARVOLT"
+            result.notAvailable = line=="NOMORE"
+        finally:
+            f.close()
+
+        return result    
+
+#------------------------------------------------------------------------------
+
+class SendACARS(Request):
+    """A request to send an ACARS to the MAVA website."""
+    _latin2Encoder = codecs.getencoder("iso-8859-2")
+
+    def __init__(self, callback, acars):
+        """Construct the request for the given PIREP."""
+        super(SendACARS, self).__init__(callback)
+        self._acars = acars
+
+    def run(self):
+        """Perform the sending of the ACARS."""
+        url = "http://www.virtualairlines.hu/acars2/acarsonline.php"
+
+        acars = self._acars
+        bookedFlight = acars.bookedFlight
+
+        data = {}
+        data["pid"] = acars.pid
+        data["pilot"] = SendACARS._latin2Encoder(acars.pilotName)[0]
+    
+        data["pass"] = str(bookedFlight.numPassengers)
+        data["callsign"] = bookedFlight.callsign
+        data["airplane"] = BookedFlight.TYPE2TYPECODE[bookedFlight.aircraftType]
+        data["from"] = bookedFlight.departureICAO
+        data["to"] = bookedFlight.arrivalICAO        
+        data["lajstrom"] = bookedFlight.tailNumber
+
+        data["block_time"] = acars.getBlockTimeText()
+        data["longitude"] = str(acars.state.longitude)
+        data["latitude"] = str(acars.state.latitude)
+        data["altitude"] = str(acars.state.altitude)
+        data["speed"] = str(acars.state.groundSpeed)
+        
+        data["event"] = acars.getEventText()
+
+        f = urllib2.urlopen(url, urllib.urlencode(data), timeout = 10.0)
+        try:
+            result = Result()
+        finally:
+            f.close()
+
+        return result    
+
+#------------------------------------------------------------------------------
+
 class Handler(threading.Thread):
     """The handler for the web services.
@@ -618,4 +762,8 @@
         """Send the given PIREP."""
         self._addRequest(SendPIREP(callback, pirep))
+
+    def sendACARS(self, callback, acars):
+        """Send the given ACARS"""
+        self._addRequest(SendACARS(callback, acars))
         
     def run(self):
