Index: src/mlx/const.py
===================================================================
--- src/mlx/const.py	(revision 82)
+++ src/mlx/const.py	(revision 97)
@@ -132,4 +132,18 @@
 #-------------------------------------------------------------------------------
 
+# Flight type: scheduled
+FLIGHTTYPE_SCHEDULED = 0
+
+# Flight type: old-timer
+FLIGHTTYPE_OLDTIMER = 1
+
+# Flight type: VIP
+FLIGHTTYPE_VIP = 2
+
+# Flight type: charter
+FLIGHTTYPE_CHARTER = 3
+
+#-------------------------------------------------------------------------------
+
 # The available gates at LHBP
 lhbpGateNumbers = []
Index: src/mlx/fsuipc.py
===================================================================
--- src/mlx/fsuipc.py	(revision 89)
+++ src/mlx/fsuipc.py	(revision 97)
@@ -642,5 +642,5 @@
  
         
-        self._aircraft.modelChanged(timestamp, self._latin1decoder(name), 
+        self._aircraft.modelChanged(timestamp, self._latin1decoder(name)[0],
                                     self._aircraftModel.name)        
 
Index: src/mlx/gui/common.py
===================================================================
--- src/mlx/gui/common.py	(revision 93)
+++ src/mlx/gui/common.py	(revision 97)
@@ -21,4 +21,5 @@
     MESSAGETYPE_ERROR = gtk.MESSAGE_ERROR
     MESSAGETYPE_QUESTION = gtk.MESSAGE_QUESTION
+    MESSAGETYPE_INFO = gtk.MESSAGE_INFO
     BUTTONSTYPE_OK = gtk.BUTTONS_OK
     BUTTONSTYPE_YES_NO = gtk.BUTTONS_YES_NO
@@ -26,4 +27,8 @@
     ACCEL_VISIBLE = gtk.ACCEL_VISIBLE
     CONTROL_MASK = gdk.CONTROL_MASK
+
+    def text2unicode(text):
+        """Convert the given text, returned by a Gtk widget, to Unicode."""
+        return unicode(text)
 else:
     print "Using PyGObject"
@@ -38,4 +43,5 @@
     MESSAGETYPE_ERROR = gtk.MessageType.ERROR
     MESSAGETYPE_QUESTION = gtk.MessageType.QUESTION
+    MESSAGETYPE_INFO = gtk.MessageType.INFO
     BUTTONSTYPE_OK = gtk.ButtonsType.OK
     BUTTONSTYPE_YES_NO = gtk.ButtonsType.YES_NO
@@ -43,4 +49,11 @@
     ACCEL_VISIBLE = gtk.AccelFlags.VISIBLE
     CONTROL_MASK = gdk.ModifierType.CONTROL_MASK
+
+    import codecs
+    _utf8Decoder = codecs.getdecoder("utf-8")
+    
+    def text2unicode(str):
+        """Convert the given text, returned by a Gtk widget, to Unicode."""
+        return _utf8Decoder(str)[0]
 
 import cairo
Index: src/mlx/gui/flight.py
===================================================================
--- src/mlx/gui/flight.py	(revision 96)
+++ src/mlx/gui/flight.py	(revision 97)
@@ -7,4 +7,5 @@
 from mlx.checks import PayloadChecker
 import mlx.util as util
+from mlx.pirep import PIREP
 
 import datetime
@@ -777,4 +778,9 @@
         self._button.connect("clicked", self._forwardClicked)
 
+    @property
+    def cargoWeight(self):
+        """Get the cargo weight entered."""
+        return self._cargoWeight.get_int()
+
     def activate(self):
         """Setup the information."""
@@ -996,5 +1002,6 @@
         self._cruiseLevel.set_numeric(True)
         self._cruiseLevel.connect("value-changed", self._cruiseLevelChanged)
-        label.set_mnemonic_widget(self._cruiseLevel)        
+        label.set_mnemonic_widget(self._cruiseLevel)
+        self._filedCruiseLevel = 240
 
         levelBox.pack_start(self._cruiseLevel, False, False, 8)
@@ -1044,11 +1051,22 @@
 
     @property
+    def filedCruiseLevel(self):
+        """Get the filed cruise level."""
+        return self._filedCruiseLevel
+
+    @property
     def cruiseLevel(self):
         """Get the cruise level."""
         return self._cruiseLevel.get_value_as_int()
 
+    @property
+    def route(self):
+        """Get the route."""
+        return self._getRoute()
+
     def activate(self):
         """Setup the route from the booked flight."""
         self._cruiseLevel.set_value(240)
+        self._filedCruiseLevel = 240
         self._route.get_buffer().set_text(self._wizard._bookedFlight.route)
         self._updateForwardButton()
@@ -1083,4 +1101,5 @@
         else:
             bookedFlight = self._wizard._bookedFlight
+            self._filedCruiseLevel = self.cruiseLevel
             self._wizard.gui.beginBusy("Downloading NOTAMs...")
             self._wizard.gui.webHandler.getNOTAMs(self._notamsCallback,
@@ -1204,4 +1223,11 @@
         self._button.connect("clicked", self._forwardClicked)
 
+    @property
+    def metar(self):
+        """Get the METAR on the page."""
+        buffer = self._metar.get_buffer()
+        return buffer.get_text(buffer.get_start_iter(),
+                               buffer.get_end_iter(), True)        
+
     def activate(self):
         """Activate the page."""
@@ -1357,4 +1383,14 @@
 
     @property
+    def runway(self):
+        """Get the runway."""
+        return self._runway.get_text()
+
+    @property
+    def sid(self):
+        """Get the SID."""
+        return self._sid.get_text()
+
+    @property
     def v1(self):
         """Get the v1 speed."""
@@ -1514,4 +1550,25 @@
 
     @property
+    def star(self):
+        """Get the STAR or None if none entered."""
+        return self._star.get_text() if self._starButton.get_active() else None
+
+    @property
+    def transition(self):
+        """Get the transition or None if none entered."""
+        return self._transition.get_text() \
+               if self._transitionButton.get_active() else None
+
+    @property
+    def approachType(self):
+        """Get the approach type."""
+        return self._approachType.get_text()
+
+    @property
+    def runway(self):
+        """Get the runway."""
+        return self._runway.get_text()
+
+    @property
     def vref(self):
         """Return the landing reference speed."""
@@ -1608,4 +1665,9 @@
 class FinishPage(Page):
     """Flight finish page."""
+    _flightTypes = [ ("scheduled", const.FLIGHTTYPE_SCHEDULED),
+                     ("old-timer", const.FLIGHTTYPE_OLDTIMER),
+                     ("VIP", const.FLIGHTTYPE_VIP),
+                     ("charter", const.FLIGHTTYPE_CHARTER) ]
+    
     def __init__(self, wizard):
         """Construct the finish page."""
@@ -1698,8 +1760,6 @@
 
         flightTypeModel = gtk.ListStore(str, int)
-        index = 1
-        for type in ["scheduled", "old-timer", "VIP", "charter"]:
-            flightTypeModel.append([type, index])
-            index += 1
+        for (name, type) in FinishPage._flightTypes:
+            flightTypeModel.append([name, type])
 
         self._flightType = gtk.ComboBox(model = flightTypeModel)
@@ -1734,5 +1794,16 @@
         self._sendButton.set_use_underline(True)
         self._sendButton.set_sensitive(False)
-        #self._sendButton.connect("clicked", self._sendClicked)
+        self._sendButton.connect("clicked", self._sendClicked)
+        
+    @property
+    def flightType(self):
+        """Get the flight type."""
+        index = self._flightType.get_active()
+        return None if index<0 else self._flightType.get_model()[index][1]
+
+    @property
+    def online(self):
+        """Get whether the flight was an online flight or not."""
+        return self._onlineFlight.get_active()
 
     def activate(self):
@@ -1770,6 +1841,50 @@
         index = self._flightType.get_active()
         flightTypeIsValid = index>=0
-        self._saveButton.set_sensitive(flightTypeIsValid)
+        #self._saveButton.set_sensitive(flightTypeIsValid)
         self._sendButton.set_sensitive(flightTypeIsValid)
+
+    def _sendClicked(self, button):
+        """Called when the Send button is clicked."""
+        pirep = PIREP(self._wizard.gui)
+        gui = self._wizard.gui
+        gui.beginBusy("Sending PIREP...")
+        gui.webHandler.sendPIREP(self._pirepSentCallback, pirep)
+
+    def _pirepSentCallback(self, returned, result):
+        """Callback for the PIREP sending result."""
+        gobject.idle_add(self._handlePIREPSent, returned, result)
+
+    def _handlePIREPSent(self, returned, result):
+        """Callback for the PIREP sending result."""
+        self._wizard.gui.endBusy()
+        secondaryMarkup = None
+        type = MESSAGETYPE_ERROR
+        if returned:
+            if result.success:
+                type = MESSAGETYPE_INFO
+                messageFormat = "The PIREP was sent successfully."
+                secondaryMarkup = "Await the thorough scrutiny from our PIREP correctors! :)"
+            elif result.alreadyFlown:
+                messageFormat = "The PIREP for this flight has already been sent!"
+                secondaryMarkup = "You may clear the old PIREP on the MAVA website."
+            elif result.notAvailable:
+                messageFormat = "This flight is not available anymore!"
+            else:
+                messageFormat = "The MAVA website returned with an unknown error."
+                secondaryMarkup = "See the debug log for more information."
+        else:
+            print "PIREP sending failed", result
+            messageFormat = "Could not send the PIREP to the MAVA website."
+            secondaryMarkup = "This can be a network problem, in which case\n" \
+                              "you may try again later. Or it can be a bug;\n" \
+                              "see the debug log for more information."
+        
+        dialog = gtk.MessageDialog(type = type, buttons = BUTTONSTYPE_OK,
+                                   message_format = messageFormat)
+        if secondaryMarkup is not None:
+            dialog.format_secondary_markup(secondaryMarkup)
+
+        dialog.run()
+        dialog.hide()
         
 #-----------------------------------------------------------------------------
@@ -1795,11 +1910,14 @@
         self._routePage = RoutePage(self)
         self._pages.append(self._routePage)
-        self._pages.append(BriefingPage(self, True))
-        self._pages.append(BriefingPage(self, False))
+        self._departureBriefingPage = BriefingPage(self, True)
+        self._pages.append(self._departureBriefingPage)
+        self._arrivalBriefingPage = BriefingPage(self, False)
+        self._pages.append(self._arrivalBriefingPage)
         self._takeoffPage = TakeoffPage(self) 
         self._pages.append(self._takeoffPage)
         self._landingPage = LandingPage(self) 
         self._pages.append(self._landingPage)
-        self._pages.append(FinishPage(self))
+        self._finishPage = FinishPage(self)
+        self._pages.append(self._finishPage)
         
         maxWidth = 0
@@ -1845,4 +1963,14 @@
 
     @property
+    def bookedFlight(self):
+        """Get the booked flight selected."""
+        return self._bookedFlight
+
+    @property
+    def cargoWeight(self):
+        """Get the calculated ZFW value."""
+        return self._payloadPage.cargoWeight
+
+    @property
     def zfw(self):
         """Get the calculated ZFW value."""
@@ -1851,4 +1979,9 @@
 
     @property
+    def filedCruiseAltitude(self):
+        """Get the filed cruise altitude."""
+        return self._routePage.filedCruiseLevel * 100
+
+    @property
     def cruiseAltitude(self):
         """Get the cruise altitude."""
@@ -1856,4 +1989,29 @@
 
     @property
+    def route(self):
+        """Get the route."""
+        return self._routePage.route
+
+    @property
+    def departureMETAR(self):
+        """Get the METAR of the departure airport."""
+        return self._departureBriefingPage.metar
+
+    @property
+    def arrivalMETAR(self):
+        """Get the METAR of the arrival airport."""
+        return self._arrivalBriefingPage.metar
+
+    @property
+    def departureRunway(self):
+        """Get the departure runway."""
+        return self._takeoffPage.runway
+
+    @property
+    def sid(self):
+        """Get the SID."""
+        return self._takeoffPage.sid
+
+    @property
     def v1(self):
         """Get the V1 speed."""
@@ -1871,7 +2029,37 @@
 
     @property
+    def arrivalRunway(self):
+        """Get the arrival runway."""
+        return self._landingPage.runway
+
+    @property
+    def star(self):
+        """Get the STAR."""
+        return self._landingPage.star
+
+    @property
+    def transition(self):
+        """Get the transition."""
+        return self._landingPage.transition
+
+    @property
+    def approachType(self):
+        """Get the approach type."""
+        return self._landingPage.approachType
+
+    @property
     def vref(self):
         """Get the Vref speed."""
         return self._landingPage.vref
+
+    @property
+    def flightType(self):
+        """Get the flight type."""
+        return self._finishPage.flightType
+
+    @property
+    def online(self):
+        """Get whether the flight was online or not."""
+        return self._finishPage.online
 
     def nextPage(self, finalize = True):
Index: src/mlx/gui/gui.py
===================================================================
--- src/mlx/gui/gui.py	(revision 96)
+++ src/mlx/gui/gui.py	(revision 97)
@@ -120,4 +120,9 @@
 
     @property
+    def logger(self):
+        """Get the logger used by us."""
+        return self._logger
+        
+    @property
     def simulator(self):
         """Get the simulator used by us."""
@@ -130,4 +135,14 @@
 
     @property
+    def bookedFlight(self):
+        """Get the booked flight selected, if any."""
+        return self._wizard.bookedFlight
+
+    @property
+    def cargoWeight(self):
+        """Get the cargo weight."""
+        return self._wizard.cargoWeight
+
+    @property
     def zfw(self):
         """Get Zero-Fuel Weight calculated for the current flight."""
@@ -135,8 +150,38 @@
         
     @property
+    def filedCruiseAltitude(self):
+        """Get cruise altitude filed for the current flight."""
+        return self._wizard.filedCruiseAltitude
+        
+    @property
     def cruiseAltitude(self):
-        """Get cruise altitude calculated for the current flight."""
+        """Get cruise altitude set for the current flight."""
         return self._wizard.cruiseAltitude
-        
+
+    @property
+    def route(self):
+        """Get the flight route."""
+        return self._wizard.route
+
+    @property
+    def departureMETAR(self):
+        """Get the METAR of the deprature airport."""
+        return self._wizard.departureMETAR
+        
+    @property
+    def arrivalMETAR(self):
+        """Get the METAR of the deprature airport."""
+        return self._wizard.arrivalMETAR
+
+    @property
+    def departureRunway(self):
+        """Get the name of the departure runway."""
+        return self._wizard.departureRunway
+        
+    @property
+    def sid(self):
+        """Get the SID."""
+        return self._wizard.sid
+
     @property
     def v1(self):
@@ -155,8 +200,48 @@
         
     @property
+    def arrivalRunway(self):
+        """Get the arrival runway."""
+        return self._wizard.arrivalRunway
+
+    @property
+    def star(self):
+        """Get the STAR."""
+        return self._wizard.star
+
+    @property
+    def transition(self):
+        """Get the transition."""
+        return self._wizard.transition
+
+    @property
+    def approachType(self):
+        """Get the approach type."""
+        return self._wizard.approachType
+
+    @property
     def vref(self):
         """Get the Vref speed calculated for the flight."""
         return self._wizard.vref
         
+    @property
+    def flightType(self):
+        """Get the flight type."""
+        return self._wizard.flightType
+
+    @property
+    def online(self):
+        """Get whether the flight was online or not."""
+        return self._wizard.online
+
+    @property
+    def comments(self):
+        """Get the comments."""
+        return self._flightInfo.comments
+
+    @property
+    def flightDefects(self):
+        """Get the flight defects."""
+        return self._flightInfo.flightDefects
+
     def run(self):
         """Run the GUI."""
Index: src/mlx/gui/info.py
===================================================================
--- src/mlx/gui/info.py	(revision 93)
+++ src/mlx/gui/info.py	(revision 97)
@@ -23,4 +23,5 @@
         
         scroller = gtk.ScrolledWindow()
+        # FIXME: these should be constants
         scroller.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
                             else gtk.POLICY_AUTOMATIC,
@@ -117,4 +118,18 @@
         self.pack_start(self._delayAlignment, False, False, 8)
 
+    @property
+    def comments(self):
+        """Get the comments."""
+        buffer = self._comments.get_buffer()
+        return text2unicode(buffer.get_text(buffer.get_start_iter(),
+                                            buffer.get_end_iter(), True))
+    
+    @property
+    def flightDefects(self):
+        """Get the flight defects."""
+        buffer = self._flightDefects.get_buffer()
+        return text2unicode(buffer.get_text(buffer.get_start_iter(),
+                                            buffer.get_end_iter(), True))
+
     def enable(self):
         """Enable the flight info tab."""
@@ -144,3 +159,2 @@
         self._weatherProblems.set_active(False)
         self._personalReasons.set_active(False)
-
Index: src/mlx/logger.py
===================================================================
--- src/mlx/logger.py	(revision 96)
+++ src/mlx/logger.py	(revision 97)
@@ -4,4 +4,5 @@
 
 import const
+import util
 
 import sys
@@ -32,10 +33,17 @@
         self._lines = []
         self._faults = {}
+        self._faultLineIndexes = []
         self._output = output
 
-    @staticmethod
-    def _getTimeStr(timestamp):
-        """Get the string representation of the given timestamp."""
-        return time.strftime("%H:%M:%S", time.gmtime(timestamp))
+    @property
+    def lines(self):
+        """Get the lines of the log."""
+        return self._lines
+
+    @property
+    def faultLineIndexes(self):
+        """Get the array of the indexes of the log line that contains a
+        fault."""
+        return self._faultLineIndexes
 
     def reset(self):
@@ -45,8 +53,9 @@
         self._lines = []
         self._faults.clear()
+        self._faultLineIndexes = []
                 
     def message(self, timestamp, msg):
         """Put a simple textual message into the log with the given timestamp."""
-        timeStr = Logger._getTimeStr(timestamp)
+        timeStr = util.getTimestampString(timestamp)
         return self._logLine(msg, timeStr)
 
@@ -78,7 +87,8 @@
         self._faults[faultID] = score
         if score==Logger.NO_GO_SCORE:
-            self.message(timestamp, "%s (NO GO)" % (what))
+            lineIndex = self.message(timestamp, "%s (NO GO)" % (what))
         else:
-            self.message(timestamp, "%s (%.1f)" % (what, score))
+            lineIndex = self.message(timestamp, "%s (%.1f)" % (what, score))
+        self._faultLineIndexes.append(lineIndex)
 
     def noGo(self, faultID, timestamp, what):
Index: src/mlx/pirep.py
===================================================================
--- src/mlx/pirep.py	(revision 97)
+++ src/mlx/pirep.py	(revision 97)
@@ -0,0 +1,97 @@
+# The PIREP class collecting all information needed for a PIREP
+
+#------------------------------------------------------------------------------
+
+import const
+
+#------------------------------------------------------------------------------
+
+class PIREP(object):
+    """A pilot's report of a flight."""
+    @staticmethod
+    def _formatLine(timeStr, line):
+        """Format the given time string and line as needed for the ACARS and
+        some other things."""
+        return "[" + timeStr + "]-[" + line + "]"
+        
+    def __init__(self, gui):
+        """Initialize the PIREP from the given GUI."""
+        self.bookedFlight = gui.bookedFlight
+        self.cargoWeight = gui.cargoWeight
+        
+        self.filedCruiseAltitude = gui.filedCruiseAltitude
+        self.cruiseAltitude = gui.cruiseAltitude
+        self.route = gui.route
+
+        self.departureMETAR = gui.departureMETAR.upper()
+        self.arrivalMETAR = gui.arrivalMETAR.upper()
+
+        self.departureRunway = gui.departureRunway.upper()
+        self.sid = gui.sid.upper()
+
+        self.star = gui.star
+        self.transition = gui.transition
+        self.approachType = gui.approachType.upper()
+        self.arrivalRunway = gui.arrivalRunway.upper()
+
+        self.flightType = gui.flightType
+        self.online = gui.online
+
+        self.comments = gui.comments
+        self.flightDefects = gui.flightDefects
+        
+        flight = gui.flight
+        self.blockTimeStart = flight.blockTimeStart
+        self.flightTimeStart = flight.flightTimeStart
+        self.flightTimeEnd = flight.flightTimeEnd
+        self.blockTimeEnd = flight.blockTimeEnd
+        self.flownDistance = flight.flownDistance
+        self.fuelUsed = flight.endFuel - flight.startFuel
+
+        logger = gui.logger
+        self.rating = logger.getRating()
+        self.logLines = logger.lines
+        self.faultLineIndexes = logger.faultLineIndexes
+        
+    def getACARSText(self):
+        """Get the ACARS text.
+
+        This is a specially formatted version of the log without the faults."""
+        text = "[MAVA LOGGER X LOG]-[%s]" % (const.VERSION,)
+        for index in range(0, len(self.logLines)):
+            if index not in self.faultLineIndexes:
+                (timeStr, line) = self.logLines[index]
+                if timeStr is not None:
+                    text += PIREP._formatLine(timeStr, line)
+        return text
+
+    def getRatingText(self):
+        """Get the rating text.
+
+        This is a specially formatted version of the lines containing the
+        faults."""
+        text = ""
+        for index in self.faultLineIndexes:
+            (timeStr, line) = self.logLines[index]
+            if timeStr is not None:
+                text += PIREP._formatLine(timeStr, line)
+                text += "\n"            
+
+        text += "\n[Flight Rating: %.1f]" % (max(0.0, self.rating),)
+
+        return text
+    
+    def getTimeComment(self):
+        """Get the time comment.
+
+        This is basically a collection of the delay codes, if any."""
+        # FIXME: implement the proper delay codes
+        return "UTC"
+
+    def getSTAR(self):
+        """Get the STAR and/or the transition."""
+        star = self.star if self.star is not None else ""
+        if self.transition is not None:
+            if star: star += ", "
+            star += self.transition
+        return star.upper()
Index: src/mlx/util.py
===================================================================
--- src/mlx/util.py	(revision 89)
+++ src/mlx/util.py	(revision 97)
@@ -2,4 +2,5 @@
 
 import math
+import time
 
 #------------------------------------------------------------------------------
@@ -75,4 +76,10 @@
 #------------------------------------------------------------------------------
 
+def getTimestampString(timestamp):
+    """Get the string representation of the given timestamp."""
+    return time.strftime("%H:%M:%S", time.gmtime(timestamp))
+
+#------------------------------------------------------------------------------
+
 def getTimeIntervalString(seconds):
     """Get a more human-friendly representation of the given time interval
@@ -81,5 +88,5 @@
     minutes = int((seconds / 60) % 60)
     seconds = int(seconds % 60)
-    return "%d:%02d:%02d" % (hours, minutes, seconds)
+    return "%02d:%02d:%02d" % (hours, minutes, seconds)
 
 #------------------------------------------------------------------------------
Index: src/mlx/web.py
===================================================================
--- src/mlx/web.py	(revision 88)
+++ src/mlx/web.py	(revision 97)
@@ -4,4 +4,5 @@
 
 import const
+import util
 
 import threading
@@ -482,4 +483,87 @@
 #------------------------------------------------------------------------------
 
+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 retrieval opf the METARs."""
+        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 Handler(threading.Thread):
     """The handler for the web services.
@@ -515,4 +599,8 @@
         """Get the METARs for the given airports."""
         self._addRequest(GetMETARs(callback, airports))
+
+    def sendPIREP(self, callback, pirep):
+        """Send the given PIREP."""
+        self._addRequest(SendPIREP(callback, pirep))
         
     def run(self):
