Commit 0a8ec2b7 authored by Volker Krause's avatar Volker Krause
Browse files

Decode 0080BL order sub-blocks

Those contain a more reliable validity time range for return tickets,
compared to all other date/time sources in here.
parent 186d09f0
Pipeline #51735 passed with stage
in 10 minutes and 51 seconds
......@@ -102,6 +102,51 @@ QString Vendor0080BLSubBlock::toString() const
}
Vendor0080BLOrderBlock::Vendor0080BLOrderBlock() = default;
Vendor0080BLOrderBlock::Vendor0080BLOrderBlock(const Uic9183Block &block, int offset)
: m_block(block)
, m_offset(offset)
{
}
bool Vendor0080BLOrderBlock::isNull() const
{
return m_block.isNull();
}
QDate Vendor0080BLOrderBlock::validFrom() const
{
switch (m_block.version()) {
case 2:
return QDate::fromString(m_block.readUtf8String(m_offset + 22, 8), QStringLiteral("ddMMyyyy"));
case 3:
return QDate::fromString(m_block.readUtf8String(m_offset, 8), QStringLiteral("ddMMyyyy"));
}
return {};
}
QDate Vendor0080BLOrderBlock::validTo() const
{
switch (m_block.version()) {
case 2:
return QDate::fromString(m_block.readUtf8String(m_offset + 22 + 8, 8), QStringLiteral("ddMMyyyy"));
case 3:
return QDate::fromString(m_block.readUtf8String(m_offset + 8, 8), QStringLiteral("ddMMyyyy"));
}
return {};
}
QString Vendor0080BLOrderBlock::serialNumber() const
{
switch (m_block.version()) {
case 2:
return m_block.readUtf8String(m_offset + 22 + 8 + 8, 8);
case 3:
return m_block.readUtf8String(m_offset + 8 + 8, 10);
}
return {};
}
// 0080BL vendor block (DB) (version 2/3, dynamic size)
// 2x stuff
// 1x number of certificate blocks
......@@ -128,6 +173,22 @@ bool Vendor0080BLBlock::isValid() const
return !m_block.isNull();
}
int Vendor0080BLBlock::orderBlockCount() const
{
return m_block.readAsciiEncodedNumber(2, 1);
}
Vendor0080BLOrderBlock Vendor0080BLBlock::orderBlock(int i) const
{
if (i >= 0 && i < orderBlockCount()) {
switch (m_block.version()) {
case 2: return Vendor0080BLOrderBlock(m_block, 3 + i * (22 + 8 + 8 + 8));
case 3: return Vendor0080BLOrderBlock(m_block, 3 + i * (8 + 8 + 10));
}
}
return {};
}
Vendor0080BLSubBlock Vendor0080BLBlock::firstBlock() const
{
return Vendor0080BLSubBlock(m_block, subblockOffset(m_block));
......
......@@ -14,6 +14,28 @@ class QString;
namespace KItinerary {
/** UIC 918.3 0080BL vendor data block order block. */
class KITINERARY_EXPORT Vendor0080BLOrderBlock
{
Q_GADGET
Q_PROPERTY(QDate validFrom READ validFrom)
Q_PROPERTY(QDate validTo READ validTo)
Q_PROPERTY(QString serialNumber READ serialNumber)
public:
Vendor0080BLOrderBlock();
Vendor0080BLOrderBlock(const Uic9183Block &block, int offset);
bool isNull() const;
QDate validFrom() const;
QDate validTo() const;
QString serialNumber() const;
private:
Uic9183Block m_block;
int m_offset = 0;
};
/** UIC 918.3 0080BL vendor data block sub-block. */
class KITINERARY_EXPORT Vendor0080BLSubBlock
{
......@@ -47,10 +69,18 @@ private:
/** UIC 918.3 0080BL vendor data block. */
class KITINERARY_EXPORT Vendor0080BLBlock
{
Q_GADGET
Q_PROPERTY(int orderBlockCount READ orderBlockCount)
public:
Vendor0080BLBlock(const Uic9183Block &block);
bool isValid() const;
int orderBlockCount() const;
/** Order block at index @p i. */
Vendor0080BLOrderBlock orderBlock(int i) const;
/** First S-block, for iterating. */
Vendor0080BLSubBlock firstBlock() const;
/** Finds a S-block by type. */
......
......@@ -95,26 +95,33 @@ static void dumpUic9183(const QByteArray &data)
// TODO dump header
for (auto block = parser.firstBlock(); !block.isNull(); block = block.nextBlock()) {
std::cout << "Block: ";
std::cout << " Block: ";
std::cout.write(block.name(), 6);
std::cout << ", size: " << block.size() << ", version: " << block.version() << std::endl;
if (block.isA<Uic9183Head>()) {
Uic9183Head head(block);
dumpGadget(&head, " ");
dumpGadget(&head, " ");
} else if (block.isA<Uic9183TicketLayout>()) {
Uic9183TicketLayout tlay(block);
std::cout << " Layout standard: " << qPrintable(tlay.type()) << std::endl;
std::cout << " Layout standard: " << qPrintable(tlay.type()) << std::endl;
for (auto field = tlay.firstField(); !field.isNull(); field = field.next()) {
std::cout << " [row: " << field.row() << " column: " << field.column()
std::cout << " [row: " << field.row() << " column: " << field.column()
<< " height: " << field.height() << " width: " << field.width()
<< " format: " << field.format() << "]: " << qPrintable(field.text())
<< std::endl;
}
} else if (block.isA<Vendor0080BLBlock>()) {
Vendor0080BLBlock vendor(block);
dumpGadget(&vendor, " ");
for (int i = 0; i < vendor.orderBlockCount(); ++i) {
const auto order = vendor.orderBlock(i);
std::cout << " Order block " << (i + 1) << ":" << std::endl;
dumpGadget(&order, " ");
}
std::cout << " S-blocks:" << std::endl;
for (auto sub = vendor.firstBlock(); !sub.isNull(); sub = sub.nextBlock()) {
std::cout << " ";
std::cout << " ";
std::cout.write(sub.id(), 3);
std::cout << " (size: " << sub.size() << "): ";
dumpRawData(sub.content(), sub.contentSize());
......@@ -122,16 +129,16 @@ static void dumpUic9183(const QByteArray &data)
}
} else if (block.isA<Vendor0080VUBlock>()) {
Vendor0080VUBlock vendor(block);
dumpGadget(vendor.commonData(), " ");
dumpGadget(vendor.commonData(), " ");
for (int i = 0; i < (int)vendor.commonData()->numberOfTickets; ++i) {
const auto ticket = vendor.ticketData(i);
std::cout << " Ticket " << (i + 1) << ":" << std::endl;
dumpGadget(ticket, " ");
dumpGadget(&ticket->validityArea, " ");
std::cout << " Ticket " << (i + 1) << ":" << std::endl;
dumpGadget(ticket, " ");
dumpGadget(&ticket->validityArea, " ");
std::cout << " payload: (hex) " << QByteArray((const char*)&ticket->validityArea + sizeof(VdvTicketValidityAreaData), ticket->validityAreaDataSize - sizeof(VdvTicketValidityAreaData)).toHex().constData() << std::endl;
}
} else {
std::cout << " Content: ";
std::cout << " Content: ";
dumpRawData(block.content(), block.contentSize());
std::cout << std::endl;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment