setLength(-1); $this->setCharacters([ 'A' => [ 0 => ' ', 1 => '!', 2 => '"', 3 => '#', 4 => '$', 5 => '%', 6 => '&', 7 => "'", 8 => '(', 9 => ')', 10 => '*', 11 => '+', 12 => ',', 13 => '-', 14 => '.', 15 => '/', 16 => '0', 17 => '1', 18 => '2', 19 => '3', 20 => '4', 21 => '5', 22 => '6', 23 => '7', 24 => '8', 25 => '9', 26 => ':', 27 => ';', 28 => '<', 29 => '=', 30 => '>', 31 => '?', 32 => '@', 33 => 'A', 34 => 'B', 35 => 'C', 36 => 'D', 37 => 'E', 38 => 'F', 39 => 'G', 40 => 'H', 41 => 'I', 42 => 'J', 43 => 'K', 44 => 'L', 45 => 'M', 46 => 'N', 47 => 'O', 48 => 'P', 49 => 'Q', 50 => 'R', 51 => 'S', 52 => 'T', 53 => 'U', 54 => 'V', 55 => 'W', 56 => 'X', 57 => 'Y', 58 => 'Z', 59 => '[', 60 => '\\', 61 => ']', 62 => '^', 63 => '_', 64 => 0x00, 65 => 0x01, 66 => 0x02, 67 => 0x03, 68 => 0x04, 69 => 0x05, 70 => 0x06, 71 => 0x07, 72 => 0x08, 73 => 0x09, 74 => 0x0A, 75 => 0x0B, 76 => 0x0C, 77 => 0x0D, 78 => 0x0E, 79 => 0x0F, 80 => 0x10, 81 => 0x11, 82 => 0x12, 83 => 0x13, 84 => 0x14, 85 => 0x15, 86 => 0x16, 87 => 0x17, 88 => 0x18, 89 => 0x19, 90 => 0x1A, 91 => 0x1B, 92 => 0x1C, 93 => 0x1D, 94 => 0x1E, 95 => 0x1F, 96 => 'Ç', 97 => 'ü', 98 => 'é', 99 => 'â', 100 => 'ä', 101 => 'à', 102 => 'å', 103 => '‡', 104 => 'ˆ', 105 => '‰', 106 => 'Š', ], 'B' => [ 0 => ' ', 1 => '!', 2 => '"', 3 => '#', 4 => '$', 5 => '%', 6 => '&', 7 => "'", 8 => '(', 9 => ')', 10 => '*', 11 => '+', 12 => ',', 13 => '-', 14 => '.', 15 => '/', 16 => '0', 17 => '1', 18 => '2', 19 => '3', 20 => '4', 21 => '5', 22 => '6', 23 => '7', 24 => '8', 25 => '9', 26 => ':', 27 => ';', 28 => '<', 29 => '=', 30 => '>', 31 => '?', 32 => '@', 33 => 'A', 34 => 'B', 35 => 'C', 36 => 'D', 37 => 'E', 38 => 'F', 39 => 'G', 40 => 'H', 41 => 'I', 42 => 'J', 43 => 'K', 44 => 'L', 45 => 'M', 46 => 'N', 47 => 'O', 48 => 'P', 49 => 'Q', 50 => 'R', 51 => 'S', 52 => 'T', 53 => 'U', 54 => 'V', 55 => 'W', 56 => 'X', 57 => 'Y', 58 => 'Z', 59 => '[', 60 => '\\', 61 => ']', 62 => '^', 63 => '_', 64 => '`', 65 => 'a', 66 => 'b', 67 => 'c', 68 => 'd', 69 => 'e', 70 => 'f', 71 => 'g', 72 => 'h', 73 => 'i', 74 => 'j', 75 => 'k', 76 => 'l', 77 => 'm', 78 => 'n', 79 => 'o', 80 => 'p', 81 => 'q', 82 => 'r', 83 => 's', 84 => 't', 85 => 'u', 86 => 'v', 87 => 'w', 88 => 'x', 89 => 'y', 90 => 'z', 91 => '{', 92 => '|', 93 => '}', 94 => '~', 95 => 0x7F, 96 => 'Ç', 97 => 'ü', 98 => 'é', 99 => 'â', 100 => 'ä', 101 => 'à', 102 => 'å', 103 => '‡', 104 => 'ˆ', 105 => '‰', 106 => 'Š', ], 'C' => [ 0 => '00', 1 => '01', 2 => '02', 3 => '03', 4 => '04', 5 => '05', 6 => '06', 7 => '07', 8 => '08', 9 => '09', 10 => '10', 11 => '11', 12 => '12', 13 => '13', 14 => '14', 15 => '15', 16 => '16', 17 => '17', 18 => '18', 19 => '19', 20 => '20', 21 => '21', 22 => '22', 23 => '23', 24 => '24', 25 => '25', 26 => '26', 27 => '27', 28 => '28', 29 => '29', 30 => '30', 31 => '31', 32 => '32', 33 => '33', 34 => '34', 35 => '35', 36 => '36', 37 => '37', 38 => '38', 39 => '39', 40 => '40', 41 => '41', 42 => '42', 43 => '43', 44 => '44', 45 => '45', 46 => '46', 47 => '47', 48 => '48', 49 => '49', 50 => '50', 51 => '51', 52 => '52', 53 => '53', 54 => '54', 55 => '55', 56 => '56', 57 => '57', 58 => '58', 59 => '59', 60 => '60', 61 => '61', 62 => '62', 63 => '63', 64 => '64', 65 => '65', 66 => '66', 67 => '67', 68 => '68', 69 => '69', 70 => '70', 71 => '71', 72 => '72', 73 => '73', 74 => '74', 75 => '75', 76 => '76', 77 => '77', 78 => '78', 79 => '79', 80 => '80', 81 => '81', 82 => '82', 83 => '83', 84 => '84', 85 => '85', 86 => '86', 87 => '87', 88 => '88', 89 => '89', 90 => '90', 91 => '91', 92 => '92', 93 => '93', 94 => '94', 95 => '95', 96 => '96', 97 => '97', 98 => '98', 99 => '99', 100 => 'ä', 101 => 'à', 102 => 'å', 103 => '‡', 104 => 'ˆ', 105 => '‰', 106 => 'Š', ], ]); $this->setChecksum('code128'); } /** * @return void */ public function setUtf8StringWrapper(StringWrapperInterface $utf8StringWrapper) { if (! $utf8StringWrapper->isSupported('UTF-8')) { throw new Exception\InvalidArgumentException( 'The string wrapper needs to support UTF-8 character encoding' ); } $this->utf8StringWrapper = $utf8StringWrapper; } /** * Get the string wrapper supporting UTF-8 character encoding * * @return StringWrapperInterface */ public function getUtf8StringWrapper() { if (! $this->utf8StringWrapper) { $this->utf8StringWrapper = StringUtils::getWrapper('UTF-8'); } return $this->utf8StringWrapper; } /** * Checks for allowed characters within the barcode * * @param string $value The barcode to check for allowed characters * @return bool */ public function hasValidCharacters($value) { if (! is_string($value)) { return false; } // get used string wrapper for UTF-8 character encoding $strWrapper = $this->getUtf8StringWrapper(); // detect starting charset $set = $this->getCodingSet($value); $read = $set; if ($set !== '') { $value = $strWrapper->substr($value, 1, null); } // process barcode while ($value !== '' && $value !== false) { $char = $strWrapper->substr($value, 0, 1); switch ($char) { // Function definition case 'Ç': case 'ü': case 'å': break; // Switch 1 char between A and B case 'é': if ($set === 'A') { $read = 'B'; break; } if ($set === 'B') { $read = 'A'; break; } break; // Switch to C case 'â': $set = 'C'; $read = 'C'; break; // Switch to B case 'ä': $set = 'B'; $read = 'B'; break; // Switch to A case 'à': $set = 'A'; $read = 'A'; break; // Doubled start character case '‡': case 'ˆ': case '‰': return false; // Chars after the stop character case 'Š': break 2; default: // Does the char exist within the charset to read? if ($this->ord128($char, $read) === -1) { return false; } break; } $value = $strWrapper->substr($value, 1, null); $read = $set; } if ($value !== '' && is_string($value) && $strWrapper->strlen($value) !== 1) { return false; } return true; } /** * Validates the checksum () * * @param string $value The barcode to validate * @return bool */ protected function code128($value) { $sum = 0; $pos = 1; $set = $this->getCodingSet($value); $read = $set; $usecheck = $this->useChecksum(null); $strWrapper = $this->getUtf8StringWrapper(); $char = $strWrapper->substr($value, 0, 1); if ($char === '‡') { $sum = 103; } elseif ($char === 'ˆ') { $sum = 104; } elseif ($char === '‰') { $sum = 105; } elseif ($usecheck === true) { // no start value, unable to detect a proper checksum return false; } $value = $strWrapper->substr($value, 1, null); while ($strWrapper->strpos($value, 'Š') || ($value !== '')) { $char = $strWrapper->substr($value, 0, 1); if ($read === 'C') { $char = $strWrapper->substr($value, 0, 2); } switch ($char) { // Function definition case 'Ç': case 'ü': case 'å': $sum += $pos * $this->ord128($char, $set); break; case 'é': $sum += $pos * $this->ord128($char, $set); if ($set === 'A') { $read = 'B'; break; } if ($set === 'B') { $read = 'A'; break; } break; // Switch to C case 'â': $sum += $pos * $this->ord128($char, $set); $set = 'C'; $read = 'C'; break; // Switch to B case 'ä': $sum += $pos * $this->ord128($char, $set); $set = 'B'; $read = 'B'; break; // Switch to A case 'à': $sum += $pos * $this->ord128($char, $set); $set = 'A'; $read = 'A'; break; case '‡': case 'ˆ': case '‰': return false; default: // Does the char exist within the charset to read? if ($this->ord128($char, $read) === -1) { return false; } $sum += $pos * $this->ord128($char, $set); break; } $value = $strWrapper->substr($value, 1); ++$pos; if (($strWrapper->strpos($value, 'Š') === 1) && ($strWrapper->strlen($value) === 2)) { // break by stop and checksum char break; } $read = $set; } if (($strWrapper->strpos($value, 'Š') !== 1) || ($strWrapper->strlen($value) !== 2)) { // return false if checksum is not readable and true if no startvalue is detected return ! $usecheck; } $mod = $sum % 103; if ($strWrapper->substr($value, 0, 1) === $this->chr128($mod, $set)) { return true; } return false; } /** * Returns the coding set for a barcode * * @param string $value Barcode * @return string */ protected function getCodingSet($value) { $value = $this->getUtf8StringWrapper()->substr($value, 0, 1); switch ($value) { case '‡': return 'A'; case 'ˆ': return 'B'; case '‰': return 'C'; } return ''; } /** * Internal method to return the code128 integer from an ascii value * * Table A * ASCII CODE128 * 32 to 95 == 0 to 63 * 0 to 31 == 64 to 95 * 128 to 138 == 96 to 106 * * Table B * ASCII CODE128 * 32 to 138 == 0 to 106 * * Table C * ASCII CODE128 * "00" to "99" == 0 to 99 * 132 to 138 == 100 to 106 * * @param string $value * @param string $set * @return int */ protected function ord128($value, $set) { $ord = ord($value); if ($set === 'A') { if ($ord < 32) { return $ord + 64; } elseif ($ord < 96) { return $ord - 32; } elseif ($ord > 138) { return -1; } else { return $ord - 32; } } elseif ($set === 'B') { if ($ord < 32) { return -1; } elseif ($ord <= 138) { return $ord - 32; } else { return -1; } } elseif ($set === 'C') { $val = (int) $value; if (($val >= 0) && ($val <= 99)) { return $val; } elseif (($ord >= 132) && ($ord <= 138)) { return $ord - 32; } else { return -1; } } else { if ($ord < 32) { return $ord + 64; } elseif ($ord <= 138) { return $ord - 32; } else { return -1; } } } /** * Internal Method to return the ascii value from a code128 integer * * Table A * ASCII CODE128 * 32 to 95 == 0 to 63 * 0 to 31 == 64 to 95 * 128 to 138 == 96 to 106 * * Table B * ASCII CODE128 * 32 to 138 == 0 to 106 * * Table C * ASCII CODE128 * "00" to "99" == 0 to 99 * 132 to 138 == 100 to 106 * * @param int $value * @param string $set * @return int|string */ protected function chr128($value, $set) { if ($set === 'A') { if ($value < 64) { return chr($value + 32); } elseif ($value < 96) { return chr($value - 64); } elseif ($value > 106) { return -1; } else { return chr($value + 32); } } elseif ($set === 'B') { if ($value > 106) { return -1; } else { return chr($value + 32); } } elseif ($set === 'C') { if (($value >= 0) && ($value <= 9)) { return '0' . (string) $value; } elseif ($value <= 99) { return (string) $value; } elseif ($value <= 106) { return chr($value + 32); } else { return -1; } } else { if ($value <= 106) { return $value + 32; } else { return -1; } } } }