@@ -154,19 +154,26 @@ static bool hrt_read_and_parse_application_info(DesfireContext_t *dctx, hrt_trav
154154 return application_id != NULL && application_id [0 ] != '\0' ;
155155}
156156
157- static void hrt_print_time ( const char * label , time_t value ) {
158- if (value == (time_t )0 ) return ;
157+ static bool hrt_format_time ( time_t value , char * out , size_t out_len ) {
158+ if (value == (time_t )0 || out == NULL || out_len == 0 ) return false ;
159159
160160 char buf [32 ] = {0 };
161161 struct tm tm_value = {0 };
162162
163163#if defined(_WIN32 )
164- if (localtime_s (& tm_value , & value ) != 0 ) return ;
164+ if (localtime_s (& tm_value , & value ) != 0 ) return false ;
165165#else
166- if (localtime_r (& value , & tm_value ) == NULL ) return ;
166+ if (localtime_r (& value , & tm_value ) == NULL ) return false ;
167167#endif
168168
169- strftime (buf , sizeof (buf ), "%Y-%m-%d %H:%M:%S" , & tm_value );
169+ if (strftime (buf , sizeof (buf ), "%Y-%m-%d %H:%M:%S" , & tm_value ) == 0 ) return false;
170+ return snprintf (out , out_len , "%s" , buf ) > 0 ;
171+ }
172+
173+ static void hrt_print_time (const char * label , time_t value ) {
174+ char buf [32 ] = {0 };
175+ if (hrt_format_time (value , buf , sizeof (buf )) == false) return ;
176+
170177 PrintAndLogEx (SUCCESS , "%s " _GREEN_ ("%s" ), label , buf );
171178}
172179
@@ -181,6 +188,85 @@ static bool hrt_has_loaded_period_info(const hrt_travel_card_t *card) {
181188 hrt_travelcard_get_period_loading_device_number (card ) > 0 ;
182189}
183190
191+ static void hrt_print_boarding_location (int location_type , int location_num ) {
192+ if (location_num <= 0 ) return ;
193+
194+ if (location_type == 1 ) {
195+ PrintAndLogEx (SUCCESS , " Boarding line.......... " _GREEN_ ("%d" ), location_num );
196+ } else if (location_type == 2 ) {
197+ PrintAndLogEx (SUCCESS , " Boarding train......... " _GREEN_ ("%d" ), location_num );
198+ }
199+ }
200+
201+ static bool hrt_format_value_ticket_zone (const hrt_eticket_t * ticket , char * out , size_t out_len ) {
202+ if (ticket == NULL || out == NULL || out_len == 0 ) return false;
203+
204+ if (hrt_eticket_get_extra_zone (ticket ) == 1 && hrt_eticket_get_group_size (ticket ) <= 1 ) {
205+ char ext1 [32 ] = {0 };
206+ char ext2 [32 ] = {0 };
207+ bool has_ext1 = false;
208+ bool has_ext2 = false;
209+ int ext1_area = hrt_eticket_get_ext1_validity_area (ticket );
210+ int ext2_area = hrt_eticket_get_ext2_validity_area (ticket );
211+
212+ if (ext1_area != 56 ) {
213+ has_ext1 = hrt_format_area (HRT_AREA_TYPE_ZONE_RANGE , ext1_area , ext1 , sizeof (ext1 ));
214+ }
215+ if (ext2_area != 56 ) {
216+ has_ext2 = hrt_format_area (HRT_AREA_TYPE_ZONE_RANGE , ext2_area , ext2 , sizeof (ext2 ));
217+ }
218+
219+ if (has_ext1 && has_ext2 ) {
220+ return snprintf (out , out_len , "%s+%s" , ext1 , ext2 ) > 0 ;
221+ }
222+ if (has_ext1 ) return snprintf (out , out_len , "%s" , ext1 ) > 0 ;
223+ if (has_ext2 ) return snprintf (out , out_len , "%s" , ext2 ) > 0 ;
224+ }
225+
226+ return hrt_format_area (hrt_eticket_get_validity_area_type (ticket ),
227+ hrt_eticket_get_validity_area (ticket ), out , out_len );
228+ }
229+
230+ static const char * hrt_history_transaction_type_name (int transaction_type ) {
231+ return transaction_type == 0 ? "Season ticket" : "Value ticket" ;
232+ }
233+
234+ static void hrt_print_history (const hrt_travel_card_t * card ) {
235+ if (card == NULL ) return ;
236+
237+ const hrt_history_t * history = hrt_travelcard_get_history (card );
238+ int history_len = hrt_travelcard_get_history_len (card );
239+ if (history == NULL || history_len <= 0 ) return ;
240+
241+ PrintAndLogEx (SUCCESS , "" );
242+ PrintAndLogEx (SUCCESS , "History records" );
243+
244+ for (int i = history_len - 1 ; i >= 0 ; i -- ) {
245+ char transaction_time [32 ] = {0 };
246+ char price_buf [32 ] = {0 };
247+
248+ if (hrt_format_time (history [i ].transaction_d_time , transaction_time , sizeof (transaction_time )) == false) {
249+ continue ;
250+ }
251+
252+ PrintAndLogEx (SUCCESS , " %s " _GREEN_ ("%s" ), transaction_time ,
253+ hrt_history_transaction_type_name (history [i ].transaction_type ));
254+
255+ if (history [i ].transaction_type != 0 &&
256+ (history [i ].group_size > 1 || history [i ].price > 0 )) {
257+ if (history [i ].group_size > 1 ) {
258+ PrintAndLogEx (SUCCESS , " Group size.......... " _GREEN_ ("%d" ), history [i ].group_size );
259+ }
260+ if (history [i ].price > 0 ) {
261+ hrt_price_to_string (history [i ].price , price_buf , sizeof (price_buf ));
262+ PrintAndLogEx (SUCCESS , " Price............... " _GREEN_ ("%s" ), price_buf );
263+ }
264+ }
265+
266+ hrt_print_time (" Transfer ends......." , history [i ].transfer_end_date );
267+ }
268+ }
269+
184270static void hrt_print_card (const hrt_travel_card_t * card ) {
185271 if (card == NULL ) return ;
186272
@@ -191,6 +277,7 @@ static void hrt_print_card(const hrt_travel_card_t *card) {
191277 const char * product_name = hrt_lookup_product_name (product_code );
192278 int area_type = hrt_travelcard_get_validity_area_type1 (card );
193279 int area = hrt_travelcard_get_validity_area1 (card );
280+ char boarding_area_buf [64 ] = {0 };
194281 const hrt_eticket_t * value_ticket = hrt_travelcard_get_value_ticket (card );
195282
196283 hrt_price_to_string (
@@ -229,6 +316,15 @@ static void hrt_print_card(const hrt_travel_card_t *card) {
229316 hrt_print_time (" Start date............." , hrt_travelcard_get_period_start_date1 (card ));
230317 hrt_print_time (" End date..............." , hrt_travelcard_get_period_end_date1 (card ));
231318 PrintAndLogEx (SUCCESS , " Length................. " _GREEN_ ("%d days" ), hrt_travelcard_get_period_length1 (card ));
319+ hrt_print_time (" Boarding time.........." , hrt_travelcard_get_boarding_date (card ));
320+ hrt_print_boarding_location (hrt_travelcard_get_boarding_location_num_type (card ),
321+ hrt_travelcard_get_boarding_location_num (card ));
322+
323+ if (hrt_format_area (hrt_travelcard_get_boarding_area_type (card ),
324+ hrt_travelcard_get_boarding_area (card ),
325+ boarding_area_buf , sizeof (boarding_area_buf ))) {
326+ PrintAndLogEx (SUCCESS , " Boarding zone.......... " _GREEN_ ("%s" ), boarding_area_buf );
327+ }
232328
233329 if (hrt_has_loaded_period_info (card )) {
234330 PrintAndLogEx (SUCCESS , " Organization........... " _GREEN_ ("%d" ), hrt_travelcard_get_period_loading_organization (card ));
@@ -240,8 +336,6 @@ static void hrt_print_card(const hrt_travel_card_t *card) {
240336 char value_area_buf [64 ] = {0 };
241337 int value_product_code = hrt_eticket_get_product_code (value_ticket );
242338 const char * value_product_name = hrt_lookup_product_name (value_product_code );
243- int value_area_type = hrt_eticket_get_validity_area_type (value_ticket );
244- int value_area = hrt_eticket_get_validity_area (value_ticket );
245339
246340 hrt_price_to_string (hrt_eticket_get_total_fare (value_ticket ), fare_buf , sizeof (fare_buf ));
247341
@@ -254,10 +348,10 @@ static void hrt_print_card(const hrt_travel_card_t *card) {
254348 PrintAndLogEx (SUCCESS , " Product code........... " _GREEN_ ("%d (unknown)" ), value_product_code );
255349 }
256350
257- if (hrt_format_area ( value_area_type , value_area , value_area_buf , sizeof (value_area_buf ))) {
258- PrintAndLogEx (SUCCESS , " Area ................... " _GREEN_ ("%s" ), value_area_buf );
351+ if (hrt_format_value_ticket_zone ( value_ticket , value_area_buf , sizeof (value_area_buf ))) {
352+ PrintAndLogEx (SUCCESS , " Zone ................... " _GREEN_ ("%s" ), value_area_buf );
259353 } else {
260- PrintAndLogEx (SUCCESS , " Area ................... " _GREEN_ ("%d (type %d)" ), value_area , value_area_type );
354+ PrintAndLogEx (SUCCESS , " Zone ................... " _GREEN_ ("unknown" ) );
261355 }
262356
263357 PrintAndLogEx (SUCCESS , " Fare................... " _GREEN_ ("%s" ), fare_buf );
@@ -266,7 +360,11 @@ static void hrt_print_card(const hrt_travel_card_t *card) {
266360 hrt_print_time (" Valid until............" , hrt_eticket_get_validity_end_date (value_ticket ));
267361 hrt_print_time (" Boarding time.........." , hrt_eticket_get_boarding_date (value_ticket ));
268362 PrintAndLogEx (SUCCESS , " Boarding vehicle....... " _GREEN_ ("%d" ), hrt_eticket_get_boarding_vehicle (value_ticket ));
363+ hrt_print_boarding_location (hrt_eticket_get_boarding_location_num_type (value_ticket ),
364+ hrt_eticket_get_boarding_location_num (value_ticket ));
269365 }
366+
367+ hrt_print_history (card );
270368}
271369
272370bool is_valid_hrt_card (DesfireContext_t * dctx , const uint8_t * aidbuf , size_t aidbuflen ) {
0 commit comments