• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

justusjonas74 / uic-918-3 / 19772118403

28 Nov 2025 07:11PM UTC coverage: 0.953%. First build
19772118403

Pull #36

github

web-flow
Merge 5e843736d into 5621c4cac
Pull Request #36: Support FCB-Barcodes

285 of 1440 branches covered (19.79%)

Branch coverage included in aggregate %.

349 of 454 new or added lines in 9 files covered. (76.87%)

2677 of 309366 relevant lines covered (0.87%)

1.22 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.86
/src/barcode-data.ts
1
import { unzipSync } from 'zlib';
3✔
2

3
import TicketContainer, { TicketContainerType } from './TicketContainer.js';
3✔
4
import { interpretField, interpretFieldResult, parseContainers, parsingFunction } from './utils.js';
3✔
5
import { SupportedTypes } from './FieldsType.js';
6
import { verifyTicket, TicketSignatureVerficationStatus } from './check_signature.js';
3✔
7

8
// Get raw data and uncompress the TicketData
9
function getVersion(data: Buffer): number {
81✔
10
  return parseInt(data.subarray(3, 5).toString(), 10);
81✔
11
}
81✔
12

13
function getLengthOfSignatureByVersion(version: number): number {
315✔
14
  if (version !== 1 && version !== 2) {
315✔
15
    throw new Error(
3✔
16
      `Barcode header contains a version of ${version} (instead of 1 or 2), which is not supported by this library yet.`
3✔
17
    );
3✔
18
  }
3✔
19
  const lengthOfSignature = version === 1 ? 50 : 64;
315✔
20
  return lengthOfSignature;
315✔
21
}
315✔
22

23
export type BarcodeHeader = {
24
  umid: Buffer;
25
  mt_version: Buffer;
26
  rics: Buffer;
27
  key_id: Buffer;
28
};
29

30
function getHeader(data: Buffer): BarcodeHeader {
78✔
31
  const umid = data.subarray(0, 3);
78✔
32
  const mt_version = data.subarray(3, 5);
78✔
33
  const rics = data.subarray(5, 9);
78✔
34
  const key_id = data.subarray(9, 14);
78✔
35
  return { umid, mt_version, rics, key_id };
78✔
36
}
78✔
37

38
function getSignature(data: Buffer, version: number): Buffer {
78✔
39
  return data.subarray(14, 14 + getLengthOfSignatureByVersion(version));
78✔
40
}
78✔
41

42
function getTicketDataLength(data: Buffer, version: number): Buffer {
78✔
43
  return data.subarray(getLengthOfSignatureByVersion(version) + 14, getLengthOfSignatureByVersion(version) + 18);
78✔
44
}
78✔
45

46
function getTicketDataRaw(data: Buffer, version: number): Buffer {
81✔
47
  return data.subarray(getLengthOfSignatureByVersion(version) + 18, data.length);
81✔
48
}
81✔
49

50
function getTicketDataUncompressed(data: Buffer): Buffer {
78✔
51
  if (data && data.length > 0) {
78✔
52
    return unzipSync(data);
75✔
53
  } else {
78✔
54
    return data;
3✔
55
  }
3✔
56
}
78✔
57

58
// Interpreters for uncompressed Ticket Data
59
export class TicketDataContainer {
3✔
60
  id: string;
73✔
61
  version: string;
108✔
62
  length: number;
108✔
63
  container_data: Buffer | interpretFieldResult;
108✔
64
  private _data: Buffer;
108✔
65
  private _initialized: boolean = false;
108✔
66

67
  constructor(data: Buffer) {
73✔
68
    this.id = data.subarray(0, 6).toString();
108✔
69
    this.version = data.subarray(6, 8).toString();
108✔
70
    this.length = parseInt(data.subarray(8, 12).toString(), 10);
108✔
71
    this._data = data.subarray(12, data.length);
108✔
72
    this.container_data = this._data;
108✔
73
  }
108✔
74

75
  async initialize(): Promise<void> {
73✔
76
    if (this._initialized) {
108!
NEW
77
      return;
×
NEW
78
    }
×
79
    this.container_data = await TicketDataContainer.parseFields(this.id, this.version, this._data);
108✔
80
    this._initialized = true;
108✔
81
  }
108✔
82

83
  static async parseFields(id: string, version: string, data: Buffer): Promise<Buffer | interpretFieldResult> {
73✔
84
    const fields = getBlockTypeFieldsByIdAndVersion(id, version);
108✔
85
    if (fields) {
108✔
86
      return await interpretField(data, fields.dataFields);
84✔
87
    } else {
84✔
88
      console.log(`ALERT: Container with id ${id} and version ${version} isn't implemented for TicketContainer ${id}.`);
24✔
89
      return data;
24✔
90
    }
24✔
91
  }
108✔
92
}
73✔
93

94
const interpretTicketContainer: parsingFunction = (data: Buffer): [TicketDataContainer, Buffer] => {
3✔
95
  const length = parseInt(data.subarray(8, 12).toString(), 10);
108✔
96
  const remainder = data.subarray(length, data.length);
108✔
97
  const container = new TicketDataContainer(data.subarray(0, length));
108✔
98
  return [container, remainder];
108✔
99
};
108✔
100

101
function getBlockTypeFieldsByIdAndVersion(id: string, version: string): TicketContainerType | undefined {
108✔
102
  return TicketContainer.find((ticketContainer) => ticketContainer.name === id && ticketContainer.version === version);
108✔
103
}
108✔
104
export type ParsedUIC918Barcode = {
105
  version: number;
106
  header: BarcodeHeader;
107
  signature: Buffer;
108
  ticketDataLength: Buffer;
109
  ticketDataRaw: Buffer;
110
  ticketDataUncompressed: Buffer;
111
  ticketContainers: SupportedTypes[];
112
  validityOfSignature?: TicketSignatureVerficationStatus;
113
  isSignatureValid?: boolean;
114
};
115
async function parseBarcodeData(data: Buffer, verifySignature: boolean = false): Promise<ParsedUIC918Barcode> {
81✔
116
  const version = getVersion(data);
81✔
117
  const ticketDataRaw = getTicketDataRaw(data, version);
81✔
118
  const ticketDataUncompressed = getTicketDataUncompressed(ticketDataRaw);
81✔
119
  const ticketContainers = parseContainers(ticketDataUncompressed, interpretTicketContainer);
81✔
120
  
121
  // Initialize all TicketDataContainer instances
122
  for (const container of ticketContainers) {
81✔
123
    if (container instanceof TicketDataContainer) {
108✔
124
      await container.initialize();
108✔
125
    }
108✔
126
  }
108✔
127
  
128
  const ticket: ParsedUIC918Barcode = {
78✔
129
    version,
78✔
130
    header: getHeader(data),
78✔
131
    signature: getSignature(data, version),
78✔
132
    ticketDataLength: getTicketDataLength(data, version),
78✔
133
    ticketDataRaw,
78✔
134
    ticketDataUncompressed,
78✔
135
    ticketContainers
78✔
136
  };
78✔
137
  if (verifySignature) {
81✔
138
    const validityOfSignature = await verifyTicket(ticket);
15✔
139
    ticket.validityOfSignature = validityOfSignature;
15✔
140
    if (validityOfSignature === TicketSignatureVerficationStatus.VALID) {
15✔
141
      ticket.isSignatureValid = true;
9✔
142
    } else if (validityOfSignature === TicketSignatureVerficationStatus.INVALID) {
12✔
143
      ticket.isSignatureValid = false;
3✔
144
    }
3✔
145
  }
15✔
146
  return ticket;
78✔
147
}
78✔
148

149
export default parseBarcodeData;
3✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc