2009-01-08 11:43:25 +03:00
/* gs1.c - Verifies GS1 data */
/*
libzint - the open source barcode library
2020-04-04 18:53:29 +03:00
Copyright ( C ) 2009 - 2020 Robin Stuart < rstuart114 @ gmail . com >
2009-01-08 11:43:25 +03:00
2013-05-16 21:26:38 +04:00
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions
are met :
2017-10-23 22:37:52 +03:00
1. Redistributions of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
2013-05-16 21:26:38 +04:00
2. Redistributions in binary form must reproduce the above copyright
notice , this list of conditions and the following disclaimer in the
2017-10-23 22:37:52 +03:00
documentation and / or other materials provided with the distribution .
2013-05-16 21:26:38 +04:00
3. Neither the name of the project nor the names of its contributors
may be used to endorse or promote products derived from this software
2017-10-23 22:37:52 +03:00
without specific prior written permission .
2013-05-16 21:26:38 +04:00
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS " AND
ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL
DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION )
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT
LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY
2017-10-23 22:37:52 +03:00
OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
2013-05-16 21:26:38 +04:00
SUCH DAMAGE .
2016-02-20 12:38:03 +03:00
*/
2019-11-05 17:16:48 +03:00
/* vim: set ts=4 sw=4 et : */
2009-01-08 11:43:25 +03:00
2009-01-11 10:42:10 +03:00
# include <stdio.h>
2009-06-03 00:23:38 +04:00
# ifdef _MSC_VER
2017-10-23 22:37:52 +03:00
# include <malloc.h>
2009-06-03 00:23:38 +04:00
# endif
2009-01-08 11:43:25 +03:00
# include "common.h"
2009-06-03 00:23:38 +04:00
# include "gs1.h"
2009-01-08 11:43:25 +03:00
2009-01-11 10:42:10 +03:00
/* This code does some checks on the integrity of GS1 data. It is not intended
to be bulletproof , nor does it report very accurately what problem was found
or where , but should prevent some of the more common encoding errors */
2019-12-19 03:37:55 +03:00
static void itostr ( char ai_string [ ] , int ai_value ) {
2016-02-20 12:38:03 +03:00
int thou , hund , ten , unit ;
char temp [ 2 ] ;
2012-12-31 17:41:59 +04:00
2016-02-20 12:38:03 +03:00
strcpy ( ai_string , " ( " ) ;
thou = ai_value / 1000 ;
hund = ( ai_value - ( 1000 * thou ) ) / 100 ;
ten = ( ai_value - ( ( 1000 * thou ) + ( 100 * hund ) ) ) / 10 ;
unit = ai_value - ( ( 1000 * thou ) + ( 100 * hund ) + ( 10 * ten ) ) ;
2012-12-31 17:41:59 +04:00
2016-02-20 12:38:03 +03:00
temp [ 1 ] = ' \0 ' ;
if ( ai_value > = 1000 ) {
temp [ 0 ] = itoc ( thou ) ;
2016-03-03 00:12:38 +03:00
strcat ( ai_string , temp ) ;
2016-02-20 12:38:03 +03:00
}
if ( ai_value > = 100 ) {
temp [ 0 ] = itoc ( hund ) ;
2016-03-03 00:12:38 +03:00
strcat ( ai_string , temp ) ;
2016-02-20 12:38:03 +03:00
}
temp [ 0 ] = itoc ( ten ) ;
2016-03-03 00:12:38 +03:00
strcat ( ai_string , temp ) ;
2016-02-20 12:38:03 +03:00
temp [ 0 ] = itoc ( unit ) ;
2016-03-03 00:12:38 +03:00
strcat ( ai_string , temp ) ;
strcat ( ai_string , " ) " ) ;
2009-01-11 23:54:27 +03:00
}
2020-07-10 21:39:32 +03:00
/* Returns the number of times a character occurs in a string */
static int ustrchr_cnt ( const unsigned char string [ ] , const size_t length , const unsigned char c ) {
int count = 0 ;
unsigned int i ;
for ( i = 0 ; i < length ; i + + ) {
if ( string [ i ] = = c ) {
count + + ;
}
}
return count ;
}
2019-12-19 03:37:55 +03:00
INTERNAL int gs1_verify ( struct zint_symbol * symbol , const unsigned char source [ ] , const size_t src_len , char reduced [ ] ) {
2016-02-20 12:38:03 +03:00
int i , j , last_ai , ai_latch ;
2019-11-10 03:27:24 +03:00
char ai_string [ 7 ] ; /* 6 char max "(NNNN)" */
2016-02-20 12:38:03 +03:00
int bracket_level , max_bracket_level , ai_length , max_ai_length , min_ai_length ;
2019-11-05 17:16:48 +03:00
int ai_count ;
2019-11-17 21:30:55 +03:00
int error_latch ;
# ifdef _MSC_VER
int * ai_value ;
int * ai_location ;
int * data_location ;
int * data_length ;
# endif
2019-11-10 03:27:24 +03:00
int ai_max = ustrchr_cnt ( source , src_len , ' [ ' ) + 1 ; /* Plus 1 so non-zero */
2019-11-05 17:16:48 +03:00
# ifndef _MSC_VER
int ai_value [ ai_max ] , ai_location [ ai_max ] , data_location [ ai_max ] , data_length [ ai_max ] ;
# else
2019-11-17 21:30:55 +03:00
ai_value = ( int * ) _alloca ( ai_max * sizeof ( int ) ) ;
ai_location = ( int * ) _alloca ( ai_max * sizeof ( int ) ) ;
data_location = ( int * ) _alloca ( ai_max * sizeof ( int ) ) ;
data_length = ( int * ) _alloca ( ai_max * sizeof ( int ) ) ;
2019-11-05 17:16:48 +03:00
# endif
2012-12-31 17:41:59 +04:00
2016-02-20 12:38:03 +03:00
/* Detect extended ASCII characters */
2020-04-04 18:53:29 +03:00
for ( i = 0 ; i < ( int ) src_len ; i + + ) {
2016-02-20 12:38:03 +03:00
if ( source [ i ] > = 128 ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 250: Extended ASCII characters are not supported by GS1 " ) ;
2016-02-20 12:38:03 +03:00
return ZINT_ERROR_INVALID_DATA ;
}
2019-10-17 12:06:21 +03:00
if ( source [ i ] = = ' \0 ' ) {
strcpy ( symbol - > errtxt , " 262: NUL characters not permitted in GS1 mode " ) ;
return ZINT_ERROR_INVALID_DATA ;
}
2016-02-20 12:38:03 +03:00
if ( source [ i ] < 32 ) {
2019-10-17 12:06:21 +03:00
strcpy ( symbol - > errtxt , " 251: Control characters are not supported by GS1 " ) ;
2016-02-20 12:38:03 +03:00
return ZINT_ERROR_INVALID_DATA ;
}
2020-05-02 02:38:35 +03:00
if ( source [ i ] = = 127 ) {
strcpy ( symbol - > errtxt , " 263: DEL characters are not supported by GS1 " ) ;
return ZINT_ERROR_INVALID_DATA ;
}
2016-02-20 12:38:03 +03:00
}
2012-12-31 17:41:59 +04:00
2016-02-20 12:38:03 +03:00
if ( source [ 0 ] ! = ' [ ' ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 252: Data does not start with an AI " ) ;
2016-02-20 12:38:03 +03:00
return ZINT_ERROR_INVALID_DATA ;
}
2012-12-31 17:41:59 +04:00
2016-02-20 12:38:03 +03:00
/* Check the position of the brackets */
bracket_level = 0 ;
max_bracket_level = 0 ;
ai_length = 0 ;
max_ai_length = 0 ;
min_ai_length = 5 ;
j = 0 ;
ai_latch = 0 ;
2020-04-04 18:53:29 +03:00
for ( i = 0 ; i < ( int ) src_len ; i + + ) {
2016-02-20 12:38:03 +03:00
ai_length + = j ;
if ( ( ( j = = 1 ) & & ( source [ i ] ! = ' ] ' ) ) & & ( ( source [ i ] < ' 0 ' ) | | ( source [ i ] > ' 9 ' ) ) ) {
ai_latch = 1 ;
}
if ( source [ i ] = = ' [ ' ) {
bracket_level + + ;
j = 1 ;
}
if ( source [ i ] = = ' ] ' ) {
bracket_level - - ;
if ( ai_length < min_ai_length ) {
min_ai_length = ai_length ;
}
j = 0 ;
ai_length = 0 ;
}
if ( bracket_level > max_bracket_level ) {
max_bracket_level = bracket_level ;
}
if ( ai_length > max_ai_length ) {
max_ai_length = ai_length ;
}
}
min_ai_length - - ;
2012-12-31 17:41:59 +04:00
2016-02-20 12:38:03 +03:00
if ( bracket_level ! = 0 ) {
/* Not all brackets are closed */
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 253: Malformed AI in input data (brackets don \' t match) " ) ;
2016-02-20 12:38:03 +03:00
return ZINT_ERROR_INVALID_DATA ;
}
2012-12-31 17:41:59 +04:00
2016-02-20 12:38:03 +03:00
if ( max_bracket_level > 1 ) {
/* Nested brackets */
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 254: Found nested brackets in input data " ) ;
2016-02-20 12:38:03 +03:00
return ZINT_ERROR_INVALID_DATA ;
}
2012-12-31 17:41:59 +04:00
2016-02-20 12:38:03 +03:00
if ( max_ai_length > 4 ) {
/* AI is too long */
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 255: Invalid AI in input data (AI too long) " ) ;
2016-02-20 12:38:03 +03:00
return ZINT_ERROR_INVALID_DATA ;
}
2012-12-31 17:41:59 +04:00
2016-02-20 12:38:03 +03:00
if ( min_ai_length < = 1 ) {
/* AI is too short */
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 256: Invalid AI in input data (AI too short) " ) ;
2016-02-20 12:38:03 +03:00
return ZINT_ERROR_INVALID_DATA ;
}
2012-12-31 17:41:59 +04:00
2016-02-20 12:38:03 +03:00
if ( ai_latch = = 1 ) {
/* Non-numeric data in AI */
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 257: Invalid AI in input data (non-numeric characters in AI) " ) ;
2016-02-20 12:38:03 +03:00
return ZINT_ERROR_INVALID_DATA ;
}
2012-12-31 17:41:59 +04:00
2016-02-20 12:38:03 +03:00
ai_count = 0 ;
2020-04-04 18:53:29 +03:00
for ( i = 1 ; i < ( int ) src_len ; i + + ) {
2016-02-20 12:38:03 +03:00
if ( source [ i - 1 ] = = ' [ ' ) {
ai_location [ ai_count ] = i ;
j = 0 ;
do {
ai_string [ j ] = source [ i + j ] ;
j + + ;
} while ( ai_string [ j - 1 ] ! = ' ] ' ) ;
ai_string [ j - 1 ] = ' \0 ' ;
ai_value [ ai_count ] = atoi ( ai_string ) ;
ai_count + + ;
}
}
2012-12-31 17:41:59 +04:00
2016-02-20 12:38:03 +03:00
for ( i = 0 ; i < ai_count ; i + + ) {
data_location [ i ] = ai_location [ i ] + 3 ;
if ( ai_value [ i ] > = 100 ) {
data_location [ i ] + + ;
}
if ( ai_value [ i ] > = 1000 ) {
data_location [ i ] + + ;
}
data_length [ i ] = 0 ;
do {
data_length [ i ] + + ;
2020-04-04 18:53:29 +03:00
} while ( ( source [ data_location [ i ] + data_length [ i ] - 1 ] ! = ' [ ' ) & & ( data_location [ i ] + data_length [ i ] < = ( int ) src_len ) ) ;
2016-02-20 12:38:03 +03:00
data_length [ i ] - - ;
}
2012-12-31 17:41:59 +04:00
2016-02-20 12:38:03 +03:00
for ( i = 0 ; i < ai_count ; i + + ) {
if ( data_length [ i ] = = 0 ) {
/* No data for given AI */
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 258: Empty data field in input data " ) ;
2016-02-20 12:38:03 +03:00
return ZINT_ERROR_INVALID_DATA ;
}
}
2018-03-30 20:46:33 +03:00
2016-02-20 12:38:03 +03:00
strcpy ( ai_string , " " ) ;
2018-03-30 20:46:33 +03:00
// Check for valid AI values and data lengths according to GS1 General
2019-03-18 19:24:07 +03:00
// Specification Release 19, January 2019
2016-02-20 12:38:03 +03:00
for ( i = 0 ; i < ai_count ; i + + ) {
2018-03-30 20:46:33 +03:00
error_latch = 2 ;
2016-02-20 12:38:03 +03:00
switch ( ai_value [ i ] ) {
2018-03-30 20:46:33 +03:00
// Length 2 Fixed
case 20 : // VARIANT
if ( data_length [ i ] ! = 2 ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
break ;
// Length 3 Fixed
case 422 : // ORIGIN
case 424 : // COUNTRY PROCESS
case 426 : // COUNTRY FULL PROCESS
if ( data_length [ i ] ! = 3 ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
break ;
// Length 4 Fixed
2019-11-10 03:27:24 +03:00
case 7040 : // UIC+EXT
2018-03-30 20:46:33 +03:00
case 8111 : // POINTS
if ( data_length [ i ] ! = 4 ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
break ;
// Length 6 Fixed
case 11 : // PROD DATE
case 12 : // DUE DATE
case 13 : // PACK DATE
case 15 : // BEST BY
case 16 : // SELL BY
case 17 : // USE BY
case 7006 : // FIRST FREEZE DATE
case 8005 : // PRICE PER UNIT
if ( data_length [ i ] ! = 6 ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
break ;
// Length 10 Fixed
case 7003 : // EXPIRY TIME
if ( data_length [ i ] ! = 10 ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
break ;
// Length 13 Fixed
case 410 : // SHIP TO LOC
case 411 : // BILL TO
case 412 : // PURCHASE FROM
case 413 : // SHIP FOR LOC
case 414 : // LOC NO
case 415 : // PAY TO
case 416 : // PROD/SERV LOC
2019-11-10 03:27:24 +03:00
case 417 : // PARTY GLN
2018-03-30 20:46:33 +03:00
case 7001 : // NSN
if ( data_length [ i ] ! = 13 ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
break ;
// Length 14 Fixed
case 1 : // GTIN
case 2 : // CONTENT
case 8001 : // DIMENSIONS
if ( data_length [ i ] ! = 14 ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
break ;
// Length 17 Fixed
case 402 : // GSIN
if ( data_length [ i ] ! = 17 ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
break ;
// Length 18 Fixed
case 0 : // SSCC
case 8006 : // ITIP
2018-07-05 23:45:11 +03:00
case 8017 : // GSRN PROVIDER
case 8018 : // GSRN RECIPIENT
2019-11-10 03:27:24 +03:00
case 8026 : // ITIP CONTENT
2018-03-30 20:46:33 +03:00
if ( data_length [ i ] ! = 18 ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
break ;
// Length 2 Max
case 7010 : // PROD METHOD
if ( data_length [ i ] > 2 ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
break ;
// Length 3 Max
case 427 : // ORIGIN SUBDIVISION
case 7008 : // AQUATIC SPECIES
if ( data_length [ i ] > 3 ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
break ;
// Length 4 Max
case 7004 : // ACTIVE POTENCY
if ( data_length [ i ] > 4 ) {
2016-02-20 12:38:03 +03:00
error_latch = 1 ;
2018-03-30 20:46:33 +03:00
} else {
error_latch = 0 ;
2016-02-20 12:38:03 +03:00
}
break ;
2018-03-30 20:46:33 +03:00
// Length 6 Max
case 242 : // MTO VARIANT
if ( data_length [ i ] > 6 ) {
2016-02-20 12:38:03 +03:00
error_latch = 1 ;
2018-03-30 20:46:33 +03:00
} else {
error_latch = 0 ;
2016-02-20 12:38:03 +03:00
}
break ;
2018-03-30 20:46:33 +03:00
// Length 8 Max
case 30 : // VAR COUNT
case 37 : // COUNT
if ( data_length [ i ] > 8 ) {
2016-02-20 12:38:03 +03:00
error_latch = 1 ;
2018-03-30 20:46:33 +03:00
} else {
error_latch = 0 ;
2016-02-20 12:38:03 +03:00
}
break ;
2018-03-30 20:46:33 +03:00
// Length 10 Max
case 7009 : // FISHING GEAR TYPE
case 8019 : // SRIN
if ( data_length [ i ] > 10 ) {
2016-02-20 12:38:03 +03:00
error_latch = 1 ;
2018-03-30 20:46:33 +03:00
} else {
error_latch = 0 ;
2016-02-20 12:38:03 +03:00
}
break ;
2018-03-30 20:46:33 +03:00
// Length 12 Max
case 7005 : // CATCH AREA
case 8011 : // CPID SERIAL
if ( data_length [ i ] > 12 ) {
2016-02-20 12:38:03 +03:00
error_latch = 1 ;
2018-03-30 20:46:33 +03:00
} else {
error_latch = 0 ;
2016-02-20 12:38:03 +03:00
}
break ;
2018-03-30 20:46:33 +03:00
// Length 20 Max
case 10 : // BATCH/LOT
case 21 : // SERIAL
case 22 : // CPV
case 243 : // PCN
case 254 : // GLN EXTENSION COMPONENT
case 420 : // SHIP TO POST
case 7020 : // REFURB LOT
case 7021 : // FUNC STAT
case 7022 : // REV STAT
case 710 : // NHRN PZN
case 711 : // NHRN CIP
case 712 : // NHRN CN
case 713 : // NHRN DRN
case 714 : // NHRN AIM
2019-11-10 03:27:24 +03:00
case 7240 : // PROTOCOL
2018-03-30 20:46:33 +03:00
case 8002 : // CMT NO
case 8012 : // VERSION
if ( data_length [ i ] > 20 ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
2016-02-20 12:38:03 +03:00
break ;
2018-03-30 20:46:33 +03:00
// Length 25 Max
case 8020 : // REF NO
if ( data_length [ i ] > 25 ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
break ;
2019-11-10 03:27:24 +03:00
// Length 28 Max
case 235 : // TPX
if ( data_length [ i ] > 28 ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
break ;
2018-03-30 20:46:33 +03:00
// Length 30 Max
case 240 : // ADDITIONAL ID
case 241 : // CUST PART NO
case 250 : // SECONDARY SERIAL
case 251 : // REF TO SOURCE
case 400 : // ORDER NUMBER
case 401 : // GINC
case 403 : // ROUTE
case 7002 : // MEAT CUT
case 7023 : // GIAI ASSEMBLY
case 8004 : // GIAI
case 8010 : // CPID
case 8013 : // BUDI-DI
case 90 : // INTERNAL
if ( data_length [ i ] > 30 ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
break ;
// Length 34 Max
case 8007 : // IBAN
if ( data_length [ i ] > 34 ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
break ;
2019-03-18 19:24:07 +03:00
// Length 50 Max
case 8009 : // OPTSEN
if ( data_length [ i ] > 50 ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
break ;
2018-03-30 20:46:33 +03:00
// Length 70 Max
case 8110 : // Coupon code
case 8112 : // Paperless coupon code
case 8200 : // PRODUCT URL
2018-07-05 23:22:27 +03:00
if ( data_length [ i ] > 70 ) {
2018-03-30 20:46:33 +03:00
error_latch = 1 ;
} else {
error_latch = 0 ;
}
break ;
}
if ( ai_value [ i ] = = 253 ) { // GDTI
2020-05-15 21:27:37 +03:00
if ( ( data_length [ i ] < 13 ) | | ( data_length [ i ] > 30 ) ) {
2018-03-30 20:46:33 +03:00
error_latch = 1 ;
} else {
error_latch = 0 ;
}
}
if ( ai_value [ i ] = = 255 ) { // GCN
2020-05-15 21:27:37 +03:00
if ( ( data_length [ i ] < 13 ) | | ( data_length [ i ] > 25 ) ) {
2018-03-30 20:46:33 +03:00
error_latch = 1 ;
} else {
error_latch = 0 ;
}
2016-02-20 12:38:03 +03:00
}
2018-03-30 20:46:33 +03:00
if ( ( ai_value [ i ] > = 3100 ) & & ( ai_value [ i ] < = 3169 ) ) {
2016-02-20 12:38:03 +03:00
if ( data_length [ i ] ! = 6 ) {
error_latch = 1 ;
2018-03-30 20:46:33 +03:00
} else {
error_latch = 0 ;
2016-02-20 12:38:03 +03:00
}
}
2018-03-30 20:46:33 +03:00
if ( ( ai_value [ i ] > = 3200 ) & & ( ai_value [ i ] < = 3379 ) ) {
if ( data_length [ i ] ! = 6 ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
2016-02-20 12:38:03 +03:00
}
2018-03-30 20:46:33 +03:00
if ( ( ai_value [ i ] > = 3400 ) & & ( ai_value [ i ] < = 3579 ) ) {
if ( data_length [ i ] ! = 6 ) {
2016-02-20 12:38:03 +03:00
error_latch = 1 ;
2018-03-30 20:46:33 +03:00
} else {
error_latch = 0 ;
2016-02-20 12:38:03 +03:00
}
}
2018-03-30 20:46:33 +03:00
if ( ( ai_value [ i ] > = 3600 ) & & ( ai_value [ i ] < = 3699 ) ) {
if ( data_length [ i ] ! = 6 ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
}
if ( ( ai_value [ i ] > = 3900 ) & & ( ai_value [ i ] < = 3909 ) ) { // AMOUNT
if ( data_length [ i ] > 15 ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
}
if ( ( ai_value [ i ] > = 3910 ) & & ( ai_value [ i ] < = 3919 ) ) { // AMOUNT
if ( ( data_length [ i ] < 4 ) | | ( data_length [ i ] > 18 ) ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
}
if ( ( ai_value [ i ] > = 3920 ) & & ( ai_value [ i ] < = 3929 ) ) { // PRICE
if ( data_length [ i ] > 15 ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
}
if ( ( ai_value [ i ] > = 3930 ) & & ( ai_value [ i ] < = 3939 ) ) { // PRICE
if ( ( data_length [ i ] < 4 ) | | ( data_length [ i ] > 18 ) ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
}
if ( ( ai_value [ i ] > = 3940 ) & & ( ai_value [ i ] < = 3949 ) ) { // PRCNT OFF
if ( data_length [ i ] ! = 4 ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
}
if ( ai_value [ i ] = = 421 ) { // SHIP TO POST
if ( ( data_length [ i ] < 4 ) | | ( data_length [ i ] > 12 ) ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
}
if ( ( ai_value [ i ] = = 423 ) | | ( ai_value [ i ] = = 425 ) ) {
// COUNTRY INITIAL PROCESS || COUNTRY DISASSEMBLY
if ( ( data_length [ i ] < 4 ) | | ( data_length [ i ] > 15 ) ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
}
if ( ai_value [ i ] = = 7007 ) { // HARVEST DATE
2019-11-10 03:27:24 +03:00
if ( ( data_length [ i ] ! = 6 ) & & ( data_length [ i ] ! = 12 ) ) {
2018-03-30 20:46:33 +03:00
error_latch = 1 ;
} else {
error_latch = 0 ;
}
}
if ( ( ai_value [ i ] > = 7030 ) & & ( ai_value [ i ] < = 7039 ) ) { // PROCESSOR #
if ( ( data_length [ i ] < 4 ) | | ( data_length [ i ] > 30 ) ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
}
2019-03-18 19:24:07 +03:00
if ( ( ai_value [ i ] > = 7230 ) & & ( ai_value [ i ] < = 7239 ) ) { // CERT #
if ( ( data_length [ i ] < 3 ) | | ( data_length [ i ] > 30 ) ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
}
2018-03-30 20:46:33 +03:00
if ( ai_value [ i ] = = 8003 ) { // GRAI
if ( ( data_length [ i ] < 15 ) | | ( data_length [ i ] > 30 ) ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
}
if ( ai_value [ i ] = = 8008 ) { // PROD TIME
2019-11-10 03:27:24 +03:00
if ( ( data_length [ i ] ! = 8 ) & & ( data_length [ i ] ! = 10 ) & & ( data_length [ i ] ! = 12 ) ) {
2018-03-30 20:46:33 +03:00
error_latch = 1 ;
} else {
error_latch = 0 ;
}
}
if ( ( ai_value [ i ] > = 91 ) & & ( ai_value [ i ] < = 99 ) ) { // INTERNAL
if ( data_length [ i ] > 90 ) {
error_latch = 1 ;
} else {
error_latch = 0 ;
}
2016-02-20 12:38:03 +03:00
}
2012-12-31 17:41:59 +04:00
2018-03-30 20:46:33 +03:00
if ( error_latch = = 1 ) {
itostr ( ai_string , ai_value [ i ] ) ;
strcpy ( symbol - > errtxt , " 259: Invalid data length for AI " ) ;
strcat ( symbol - > errtxt , ai_string ) ;
return ZINT_ERROR_INVALID_DATA ;
}
2012-12-31 17:41:59 +04:00
2018-03-30 20:46:33 +03:00
if ( error_latch = = 2 ) {
itostr ( ai_string , ai_value [ i ] ) ;
strcpy ( symbol - > errtxt , " 260: Invalid AI value " ) ;
strcat ( symbol - > errtxt , ai_string ) ;
return ZINT_ERROR_INVALID_DATA ;
}
2016-02-20 12:38:03 +03:00
}
2009-01-11 10:42:10 +03:00
2016-02-20 12:38:03 +03:00
/* Resolve AI data - put resulting string in 'reduced' */
j = 0 ;
ai_latch = 1 ;
2020-04-04 18:53:29 +03:00
for ( i = 0 ; i < ( int ) src_len ; i + + ) {
2016-02-20 12:38:03 +03:00
if ( ( source [ i ] ! = ' [ ' ) & & ( source [ i ] ! = ' ] ' ) ) {
reduced [ j + + ] = source [ i ] ;
}
if ( source [ i ] = = ' [ ' ) {
/* Start of an AI string */
if ( ai_latch = = 0 ) {
reduced [ j + + ] = ' [ ' ;
}
ai_string [ 0 ] = source [ i + 1 ] ;
ai_string [ 1 ] = source [ i + 2 ] ;
ai_string [ 2 ] = ' \0 ' ;
last_ai = atoi ( ai_string ) ;
ai_latch = 0 ;
2020-08-05 08:53:06 +03:00
/* The following values from "GS-1 General Specification Release 20.0"
figure 7.8 .4 - 2 " Element Strings with Predefined Length Using Application Identifiers " */
2016-02-20 12:38:03 +03:00
if (
( ( last_ai > = 0 ) & & ( last_ai < = 4 ) )
| | ( ( last_ai > = 11 ) & & ( last_ai < = 20 ) )
2020-08-05 08:53:06 +03:00
| | ( last_ai = = 23 ) /* legacy support */
2016-02-20 12:38:03 +03:00
| | ( ( last_ai > = 31 ) & & ( last_ai < = 36 ) )
| | ( last_ai = = 41 )
) {
ai_latch = 1 ;
}
}
/* The ']' character is simply dropped from the input */
}
reduced [ j ] = ' \0 ' ;
2012-12-31 17:41:59 +04:00
2016-02-20 12:38:03 +03:00
/* the character '[' in the reduced string refers to the FNC1 character */
return 0 ;
2009-01-13 23:42:45 +03:00
}