From f9c160d6256ff0592906f7a79d669975a14f3c98 Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Tue, 8 Dec 2015 06:50:07 +0100 Subject: [PATCH] refs #533, fix callsign validation and split into functions for ATC/aircraft --- src/blackcore/airspacemonitor.cpp | 4 +- .../components/flightplancomponent.cpp | 2 +- src/blackgui/components/logincomponent.cpp | 4 +- src/blackgui/components/mappingcomponent.cpp | 2 +- src/blackmisc/aviation/callsign.cpp | 42 +++++++++++++++++-- src/blackmisc/aviation/callsign.h | 16 ++++++- src/blackmisc/simulation/simulatedaircraft.h | 2 +- 7 files changed, 60 insertions(+), 12 deletions(-) diff --git a/src/blackcore/airspacemonitor.cpp b/src/blackcore/airspacemonitor.cpp index 261a142cd..343322a48 100644 --- a/src/blackcore/airspacemonitor.cpp +++ b/src/blackcore/airspacemonitor.cpp @@ -785,7 +785,9 @@ namespace BlackCore void CAirspaceMonitor::icaoOrFsdDataReceived(const CCallsign &callsign, const QString &aircraftIcaoDesignator, const QString &airlineIcaoDesignator, const QString &livery, const QString &modelString, CAircraftModel::ModelType type) { Q_ASSERT_X(CThreadUtils::isCurrentThreadObjectThread(this), Q_FUNC_INFO, "not in main thread"); - Q_ASSERT_X(!callsign.isEmpty(), Q_FUNC_INFO, "no callsign"); + BLACK_VERIFY_X(callsign.isValid(), Q_FUNC_INFO, "invalid callsign"); + if (!callsign.isValid()) { return; } + if (!this->m_connected) { return; } if (aircraftIcaoDesignator.isEmpty() && airlineIcaoDesignator.isEmpty() && livery.isEmpty()) { return; } diff --git a/src/blackgui/components/flightplancomponent.cpp b/src/blackgui/components/flightplancomponent.cpp index 70c3c0029..b362dfb53 100644 --- a/src/blackgui/components/flightplancomponent.cpp +++ b/src/blackgui/components/flightplancomponent.cpp @@ -73,7 +73,7 @@ namespace BlackGui void CFlightPlanComponent::prefillWithAircraftData(const BlackMisc::Simulation::CSimulatedAircraft &ownAircraft) { // only override with valid values - if (CCallsign::isValidCallsign(ownAircraft.getCallsignAsString())) + if (CCallsign::isValidAircraftCallsign(ownAircraft.getCallsignAsString())) { this->ui->le_Callsign->setText(ownAircraft.getCallsign().asString()); } diff --git a/src/blackgui/components/logincomponent.cpp b/src/blackgui/components/logincomponent.cpp index e6f8ae1fc..ebbc618f2 100644 --- a/src/blackgui/components/logincomponent.cpp +++ b/src/blackgui/components/logincomponent.cpp @@ -423,7 +423,7 @@ namespace BlackGui bool validIcaoDesignator = CAircraftIcaoCode::isValidDesignator(values.ownAircraftIcaoTypeDesignator); this->ui->lblp_AircraftIcaoDesignator->setTicked(validIcaoDesignator); - bool validCallsign = CCallsign::isValidCallsign(values.ownCallsign); + bool validCallsign = CCallsign::isValidAircraftCallsign(values.ownCallsign); this->ui->lblp_Callsign->setTicked(validCallsign); bool validSimulatorModel = !values.ownAircraftSimulatorModel.isEmpty(); @@ -486,7 +486,7 @@ namespace BlackGui } else { - CLogMessage(this).validationWarning("Reverse lookup for %1 failed") << model.getModelString(); + CLogMessage(this).validationInfo("Reverse lookup for %1 failed, set data manually") << model.getModelString(); } } diff --git a/src/blackgui/components/mappingcomponent.cpp b/src/blackgui/components/mappingcomponent.cpp index 5b6f18b0c..67bc220a6 100644 --- a/src/blackgui/components/mappingcomponent.cpp +++ b/src/blackgui/components/mappingcomponent.cpp @@ -211,7 +211,7 @@ namespace BlackGui { Q_ASSERT(getIContextSimulator()); QString cs = ui->le_Callsign->text().trimmed(); - if (!CCallsign::isValidCallsign(cs)) + if (!CCallsign::isValidAircraftCallsign(cs)) { CLogMessage(this).validationError("Invalid callsign for mapping"); return; diff --git a/src/blackmisc/aviation/callsign.cpp b/src/blackmisc/aviation/callsign.cpp index b3a3a8de8..b345b03fd 100644 --- a/src/blackmisc/aviation/callsign.cpp +++ b/src/blackmisc/aviation/callsign.cpp @@ -187,26 +187,60 @@ namespace BlackMisc return 0; } - bool CCallsign::isValidCallsign(const QString &callsign) + bool CCallsign::isValid() const + { + switch (m_typeHint) + { + case Atc: + return isValidAtcCallsign(*this); + case Aircraft: + return isValidAircraftCallsign(*this); + default: + return !this->isEmpty(); + } + } + + bool CCallsign::isValidAircraftCallsign(const QString &callsign) { - // We allow all number callsigns if (callsign.length() < 2 || callsign.length() > 10) { return false; } + // We allow all number callsigns static QThreadStorage tsRegex; if (! tsRegex.hasLocalData()) { tsRegex.setLocalData(QRegularExpression("^[A-Z0-9]*$")); } const QRegularExpression ®exp = tsRegex.localData(); return (regexp.match(callsign).hasMatch()); } + bool CCallsign::isValidAircraftCallsign(const CCallsign &callsign) + { + return isValidAircraftCallsign(callsign.asString()); + } + + bool CCallsign::isValidAtcCallsign(const QString &callsign) + { + if (callsign.length() < 2 || callsign.length() > 10) { return false; } + + // We allow all number callsigns + static QThreadStorage tsRegex; + if (! tsRegex.hasLocalData()) { tsRegex.setLocalData(QRegularExpression("^[A-Z0-9_]*$")); } + const QRegularExpression ®exp = tsRegex.localData(); + return (regexp.match(callsign).hasMatch()); + } + + bool CCallsign::isValidAtcCallsign(const CCallsign &callsign) + { + return isValidAtcCallsign(callsign.asString()); + } + const QStringList &CCallsign::atcCallsignSuffixes() { - static const QStringList a( { "APP", "GND", "TWR", "DEL", "CTR" }); + static const QStringList a({ "APP", "GND", "TWR", "DEL", "CTR" }); return a; } const QStringList &CCallsign::atcAlikeCallsignSuffixes() { - static const QStringList a( { "ATIS", "APP", "GND", "OBS", "TWR", "DEL", "CTR", "SUP", "FSS" }); + static const QStringList a({ "ATIS", "APP", "GND", "OBS", "TWR", "DEL", "CTR", "SUP", "FSS" }); return a; } diff --git a/src/blackmisc/aviation/callsign.h b/src/blackmisc/aviation/callsign.h index 2f6251251..6dd416ef5 100644 --- a/src/blackmisc/aviation/callsign.h +++ b/src/blackmisc/aviation/callsign.h @@ -78,7 +78,7 @@ namespace BlackMisc //! Supervisor? bool isSupervisorCallsign() const; - //! Get callsign. + //! Get callsign (normalized) const QString &asString() const { return this->m_callsign; } //! Get callsign. @@ -121,7 +121,19 @@ namespace BlackMisc int comparePropertyByIndex(const CCallsign &compareValue, const CPropertyIndex &index) const; //! Valid callsign? - static bool isValidCallsign(const QString &callsign); + bool isValid() const; + + //! Valid callsign? + static bool isValidAircraftCallsign(const QString &callsign); + + //! Valid callsign? + static bool isValidAircraftCallsign(const CCallsign &callsign); + + //! Valid callsign? + static bool isValidAtcCallsign(const QString &callsign); + + //! Valid callsign? + static bool isValidAtcCallsign(const CCallsign &callsign); //! List of real ATC suffixes (e.g. TWR); static const QStringList &atcCallsignSuffixes(); diff --git a/src/blackmisc/simulation/simulatedaircraft.h b/src/blackmisc/simulation/simulatedaircraft.h index 4c04bc75c..5df58aa6e 100644 --- a/src/blackmisc/simulation/simulatedaircraft.h +++ b/src/blackmisc/simulation/simulatedaircraft.h @@ -140,7 +140,7 @@ namespace BlackMisc bool hasAircraftAndAirlineDesignator() const; //! Valid callsign? - bool hasValidCallsign() const { return BlackMisc::Aviation::CCallsign::isValidCallsign(this->getCallsign().asString()); } + bool hasValidCallsign() const { return BlackMisc::Aviation::CCallsign::isValidAircraftCallsign(this->getCallsign().asString()); } //! Callsign not empty, no further checks bool hasCallsign() const { return !getCallsign().isEmpty(); }