1 /* imail.c - Handles Intelligent Mail (aka OneCode) for USPS */
2
3 /*
4 libzint - the open source barcode library
5 Copyright (C) 2008-2017 Robin Stuart <rstuart114@gmail.com>
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10
11 1. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
16 3. Neither the name of the project nor the names of its contributors
17 may be used to endorse or promote products derived from this software
18 without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 SUCH DAMAGE.
31 */
32
33 /* The function "USPS_MSB_Math_CRC11GenerateFrameCheckSequence"
34 is Copyright (C) 2006 United States Postal Service */
35
36 #include <string.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include "common.h"
40 #include "large.h"
41
42 #define SODIUM "0123456789-"
43
44 /* The following lookup tables were generated using the code in Appendix C */
45
46 static const unsigned short AppxD_I[1287] = {
47 /* Appendix D Table 1 - 5 of 13 characters */
48 0x001F, 0x1F00, 0x002F, 0x1E80, 0x0037, 0x1D80, 0x003B, 0x1B80, 0x003D, 0x1780,
49 0x003E, 0x0F80, 0x004F, 0x1E40, 0x0057, 0x1D40, 0x005B, 0x1B40, 0x005D, 0x1740,
50 0x005E, 0x0F40, 0x0067, 0x1CC0, 0x006B, 0x1AC0, 0x006D, 0x16C0, 0x006E, 0x0EC0,
51 0x0073, 0x19C0, 0x0075, 0x15C0, 0x0076, 0x0DC0, 0x0079, 0x13C0, 0x007A, 0x0BC0,
52 0x007C, 0x07C0, 0x008F, 0x1E20, 0x0097, 0x1D20, 0x009B, 0x1B20, 0x009D, 0x1720,
53 0x009E, 0x0F20, 0x00A7, 0x1CA0, 0x00AB, 0x1AA0, 0x00AD, 0x16A0, 0x00AE, 0x0EA0,
54 0x00B3, 0x19A0, 0x00B5, 0x15A0, 0x00B6, 0x0DA0, 0x00B9, 0x13A0, 0x00BA, 0x0BA0,
55 0x00BC, 0x07A0, 0x00C7, 0x1C60, 0x00CB, 0x1A60, 0x00CD, 0x1660, 0x00CE, 0x0E60,
56 0x00D3, 0x1960, 0x00D5, 0x1560, 0x00D6, 0x0D60, 0x00D9, 0x1360, 0x00DA, 0x0B60,
57 0x00DC, 0x0760, 0x00E3, 0x18E0, 0x00E5, 0x14E0, 0x00E6, 0x0CE0, 0x00E9, 0x12E0,
58 0x00EA, 0x0AE0, 0x00EC, 0x06E0, 0x00F1, 0x11E0, 0x00F2, 0x09E0, 0x00F4, 0x05E0,
59 0x00F8, 0x03E0, 0x010F, 0x1E10, 0x0117, 0x1D10, 0x011B, 0x1B10, 0x011D, 0x1710,
60 0x011E, 0x0F10, 0x0127, 0x1C90, 0x012B, 0x1A90, 0x012D, 0x1690, 0x012E, 0x0E90,
61 0x0133, 0x1990, 0x0135, 0x1590, 0x0136, 0x0D90, 0x0139, 0x1390, 0x013A, 0x0B90,
62 0x013C, 0x0790, 0x0147, 0x1C50, 0x014B, 0x1A50, 0x014D, 0x1650, 0x014E, 0x0E50,
63 0x0153, 0x1950, 0x0155, 0x1550, 0x0156, 0x0D50, 0x0159, 0x1350, 0x015A, 0x0B50,
64 0x015C, 0x0750, 0x0163, 0x18D0, 0x0165, 0x14D0, 0x0166, 0x0CD0, 0x0169, 0x12D0,
65 0x016A, 0x0AD0, 0x016C, 0x06D0, 0x0171, 0x11D0, 0x0172, 0x09D0, 0x0174, 0x05D0,
66 0x0178, 0x03D0, 0x0187, 0x1C30, 0x018B, 0x1A30, 0x018D, 0x1630, 0x018E, 0x0E30,
67 0x0193, 0x1930, 0x0195, 0x1530, 0x0196, 0x0D30, 0x0199, 0x1330, 0x019A, 0x0B30,
68 0x019C, 0x0730, 0x01A3, 0x18B0, 0x01A5, 0x14B0, 0x01A6, 0x0CB0, 0x01A9, 0x12B0,
69 0x01AA, 0x0AB0, 0x01AC, 0x06B0, 0x01B1, 0x11B0, 0x01B2, 0x09B0, 0x01B4, 0x05B0,
70 0x01B8, 0x03B0, 0x01C3, 0x1870, 0x01C5, 0x1470, 0x01C6, 0x0C70, 0x01C9, 0x1270,
71 0x01CA, 0x0A70, 0x01CC, 0x0670, 0x01D1, 0x1170, 0x01D2, 0x0970, 0x01D4, 0x0570,
72 0x01D8, 0x0370, 0x01E1, 0x10F0, 0x01E2, 0x08F0, 0x01E4, 0x04F0, 0x01E8, 0x02F0,
73 0x020F, 0x1E08, 0x0217, 0x1D08, 0x021B, 0x1B08, 0x021D, 0x1708, 0x021E, 0x0F08,
74 0x0227, 0x1C88, 0x022B, 0x1A88, 0x022D, 0x1688, 0x022E, 0x0E88, 0x0233, 0x1988,
75 0x0235, 0x1588, 0x0236, 0x0D88, 0x0239, 0x1388, 0x023A, 0x0B88, 0x023C, 0x0788,
76 0x0247, 0x1C48, 0x024B, 0x1A48, 0x024D, 0x1648, 0x024E, 0x0E48, 0x0253, 0x1948,
77 0x0255, 0x1548, 0x0256, 0x0D48, 0x0259, 0x1348, 0x025A, 0x0B48, 0x025C, 0x0748,
78 0x0263, 0x18C8, 0x0265, 0x14C8, 0x0266, 0x0CC8, 0x0269, 0x12C8, 0x026A, 0x0AC8,
79 0x026C, 0x06C8, 0x0271, 0x11C8, 0x0272, 0x09C8, 0x0274, 0x05C8, 0x0278, 0x03C8,
80 0x0287, 0x1C28, 0x028B, 0x1A28, 0x028D, 0x1628, 0x028E, 0x0E28, 0x0293, 0x1928,
81 0x0295, 0x1528, 0x0296, 0x0D28, 0x0299, 0x1328, 0x029A, 0x0B28, 0x029C, 0x0728,
82 0x02A3, 0x18A8, 0x02A5, 0x14A8, 0x02A6, 0x0CA8, 0x02A9, 0x12A8, 0x02AA, 0x0AA8,
83 0x02AC, 0x06A8, 0x02B1, 0x11A8, 0x02B2, 0x09A8, 0x02B4, 0x05A8, 0x02B8, 0x03A8,
84 0x02C3, 0x1868, 0x02C5, 0x1468, 0x02C6, 0x0C68, 0x02C9, 0x1268, 0x02CA, 0x0A68,
85 0x02CC, 0x0668, 0x02D1, 0x1168, 0x02D2, 0x0968, 0x02D4, 0x0568, 0x02D8, 0x0368,
86 0x02E1, 0x10E8, 0x02E2, 0x08E8, 0x02E4, 0x04E8, 0x0307, 0x1C18, 0x030B, 0x1A18,
87 0x030D, 0x1618, 0x030E, 0x0E18, 0x0313, 0x1918, 0x0315, 0x1518, 0x0316, 0x0D18,
88 0x0319, 0x1318, 0x031A, 0x0B18, 0x031C, 0x0718, 0x0323, 0x1898, 0x0325, 0x1498,
89 0x0326, 0x0C98, 0x0329, 0x1298, 0x032A, 0x0A98, 0x032C, 0x0698, 0x0331, 0x1198,
90 0x0332, 0x0998, 0x0334, 0x0598, 0x0338, 0x0398, 0x0343, 0x1858, 0x0345, 0x1458,
91 0x0346, 0x0C58, 0x0349, 0x1258, 0x034A, 0x0A58, 0x034C, 0x0658, 0x0351, 0x1158,
92 0x0352, 0x0958, 0x0354, 0x0558, 0x0361, 0x10D8, 0x0362, 0x08D8, 0x0364, 0x04D8,
93 0x0383, 0x1838, 0x0385, 0x1438, 0x0386, 0x0C38, 0x0389, 0x1238, 0x038A, 0x0A38,
94 0x038C, 0x0638, 0x0391, 0x1138, 0x0392, 0x0938, 0x0394, 0x0538, 0x03A1, 0x10B8,
95 0x03A2, 0x08B8, 0x03A4, 0x04B8, 0x03C1, 0x1078, 0x03C2, 0x0878, 0x03C4, 0x0478,
96 0x040F, 0x1E04, 0x0417, 0x1D04, 0x041B, 0x1B04, 0x041D, 0x1704, 0x041E, 0x0F04,
97 0x0427, 0x1C84, 0x042B, 0x1A84, 0x042D, 0x1684, 0x042E, 0x0E84, 0x0433, 0x1984,
98 0x0435, 0x1584, 0x0436, 0x0D84, 0x0439, 0x1384, 0x043A, 0x0B84, 0x043C, 0x0784,
99 0x0447, 0x1C44, 0x044B, 0x1A44, 0x044D, 0x1644, 0x044E, 0x0E44, 0x0453, 0x1944,
100 0x0455, 0x1544, 0x0456, 0x0D44, 0x0459, 0x1344, 0x045A, 0x0B44, 0x045C, 0x0744,
101 0x0463, 0x18C4, 0x0465, 0x14C4, 0x0466, 0x0CC4, 0x0469, 0x12C4, 0x046A, 0x0AC4,
102 0x046C, 0x06C4, 0x0471, 0x11C4, 0x0472, 0x09C4, 0x0474, 0x05C4, 0x0487, 0x1C24,
103 0x048B, 0x1A24, 0x048D, 0x1624, 0x048E, 0x0E24, 0x0493, 0x1924, 0x0495, 0x1524,
104 0x0496, 0x0D24, 0x0499, 0x1324, 0x049A, 0x0B24, 0x049C, 0x0724, 0x04A3, 0x18A4,
105 0x04A5, 0x14A4, 0x04A6, 0x0CA4, 0x04A9, 0x12A4, 0x04AA, 0x0AA4, 0x04AC, 0x06A4,
106 0x04B1, 0x11A4, 0x04B2, 0x09A4, 0x04B4, 0x05A4, 0x04C3, 0x1864, 0x04C5, 0x1464,
107 0x04C6, 0x0C64, 0x04C9, 0x1264, 0x04CA, 0x0A64, 0x04CC, 0x0664, 0x04D1, 0x1164,
108 0x04D2, 0x0964, 0x04D4, 0x0564, 0x04E1, 0x10E4, 0x04E2, 0x08E4, 0x0507, 0x1C14,
109 0x050B, 0x1A14, 0x050D, 0x1614, 0x050E, 0x0E14, 0x0513, 0x1914, 0x0515, 0x1514,
110 0x0516, 0x0D14, 0x0519, 0x1314, 0x051A, 0x0B14, 0x051C, 0x0714, 0x0523, 0x1894,
111 0x0525, 0x1494, 0x0526, 0x0C94, 0x0529, 0x1294, 0x052A, 0x0A94, 0x052C, 0x0694,
112 0x0531, 0x1194, 0x0532, 0x0994, 0x0534, 0x0594, 0x0543, 0x1854, 0x0545, 0x1454,
113 0x0546, 0x0C54, 0x0549, 0x1254, 0x054A, 0x0A54, 0x054C, 0x0654, 0x0551, 0x1154,
114 0x0552, 0x0954, 0x0561, 0x10D4, 0x0562, 0x08D4, 0x0583, 0x1834, 0x0585, 0x1434,
115 0x0586, 0x0C34, 0x0589, 0x1234, 0x058A, 0x0A34, 0x058C, 0x0634, 0x0591, 0x1134,
116 0x0592, 0x0934, 0x05A1, 0x10B4, 0x05A2, 0x08B4, 0x05C1, 0x1074, 0x05C2, 0x0874,
117 0x0607, 0x1C0C, 0x060B, 0x1A0C, 0x060D, 0x160C, 0x060E, 0x0E0C, 0x0613, 0x190C,
118 0x0615, 0x150C, 0x0616, 0x0D0C, 0x0619, 0x130C, 0x061A, 0x0B0C, 0x061C, 0x070C,
119 0x0623, 0x188C, 0x0625, 0x148C, 0x0626, 0x0C8C, 0x0629, 0x128C, 0x062A, 0x0A8C,
120 0x062C, 0x068C, 0x0631, 0x118C, 0x0632, 0x098C, 0x0643, 0x184C, 0x0645, 0x144C,
121 0x0646, 0x0C4C, 0x0649, 0x124C, 0x064A, 0x0A4C, 0x0651, 0x114C, 0x0652, 0x094C,
122 0x0661, 0x10CC, 0x0662, 0x08CC, 0x0683, 0x182C, 0x0685, 0x142C, 0x0686, 0x0C2C,
123 0x0689, 0x122C, 0x068A, 0x0A2C, 0x0691, 0x112C, 0x0692, 0x092C, 0x06A1, 0x10AC,
124 0x06A2, 0x08AC, 0x06C1, 0x106C, 0x06C2, 0x086C, 0x0703, 0x181C, 0x0705, 0x141C,
125 0x0706, 0x0C1C, 0x0709, 0x121C, 0x070A, 0x0A1C, 0x0711, 0x111C, 0x0712, 0x091C,
126 0x0721, 0x109C, 0x0722, 0x089C, 0x0741, 0x105C, 0x0742, 0x085C, 0x0781, 0x103C,
127 0x0782, 0x083C, 0x080F, 0x1E02, 0x0817, 0x1D02, 0x081B, 0x1B02, 0x081D, 0x1702,
128 0x081E, 0x0F02, 0x0827, 0x1C82, 0x082B, 0x1A82, 0x082D, 0x1682, 0x082E, 0x0E82,
129 0x0833, 0x1982, 0x0835, 0x1582, 0x0836, 0x0D82, 0x0839, 0x1382, 0x083A, 0x0B82,
130 0x0847, 0x1C42, 0x084B, 0x1A42, 0x084D, 0x1642, 0x084E, 0x0E42, 0x0853, 0x1942,
131 0x0855, 0x1542, 0x0856, 0x0D42, 0x0859, 0x1342, 0x085A, 0x0B42, 0x0863, 0x18C2,
132 0x0865, 0x14C2, 0x0866, 0x0CC2, 0x0869, 0x12C2, 0x086A, 0x0AC2, 0x0871, 0x11C2,
133 0x0872, 0x09C2, 0x0887, 0x1C22, 0x088B, 0x1A22, 0x088D, 0x1622, 0x088E, 0x0E22,
134 0x0893, 0x1922, 0x0895, 0x1522, 0x0896, 0x0D22, 0x0899, 0x1322, 0x089A, 0x0B22,
135 0x08A3, 0x18A2, 0x08A5, 0x14A2, 0x08A6, 0x0CA2, 0x08A9, 0x12A2, 0x08AA, 0x0AA2,
136 0x08B1, 0x11A2, 0x08B2, 0x09A2, 0x08C3, 0x1862, 0x08C5, 0x1462, 0x08C6, 0x0C62,
137 0x08C9, 0x1262, 0x08CA, 0x0A62, 0x08D1, 0x1162, 0x08D2, 0x0962, 0x08E1, 0x10E2,
138 0x0907, 0x1C12, 0x090B, 0x1A12, 0x090D, 0x1612, 0x090E, 0x0E12, 0x0913, 0x1912,
139 0x0915, 0x1512, 0x0916, 0x0D12, 0x0919, 0x1312, 0x091A, 0x0B12, 0x0923, 0x1892,
140 0x0925, 0x1492, 0x0926, 0x0C92, 0x0929, 0x1292, 0x092A, 0x0A92, 0x0931, 0x1192,
141 0x0932, 0x0992, 0x0943, 0x1852, 0x0945, 0x1452, 0x0946, 0x0C52, 0x0949, 0x1252,
142 0x094A, 0x0A52, 0x0951, 0x1152, 0x0961, 0x10D2, 0x0983, 0x1832, 0x0985, 0x1432,
143 0x0986, 0x0C32, 0x0989, 0x1232, 0x098A, 0x0A32, 0x0991, 0x1132, 0x09A1, 0x10B2,
144 0x09C1, 0x1072, 0x0A07, 0x1C0A, 0x0A0B, 0x1A0A, 0x0A0D, 0x160A, 0x0A0E, 0x0E0A,
145 0x0A13, 0x190A, 0x0A15, 0x150A, 0x0A16, 0x0D0A, 0x0A19, 0x130A, 0x0A1A, 0x0B0A,
146 0x0A23, 0x188A, 0x0A25, 0x148A, 0x0A26, 0x0C8A, 0x0A29, 0x128A, 0x0A2A, 0x0A8A,
147 0x0A31, 0x118A, 0x0A43, 0x184A, 0x0A45, 0x144A, 0x0A46, 0x0C4A, 0x0A49, 0x124A,
148 0x0A51, 0x114A, 0x0A61, 0x10CA, 0x0A83, 0x182A, 0x0A85, 0x142A, 0x0A86, 0x0C2A,
149 0x0A89, 0x122A, 0x0A91, 0x112A, 0x0AA1, 0x10AA, 0x0AC1, 0x106A, 0x0B03, 0x181A,
150 0x0B05, 0x141A, 0x0B06, 0x0C1A, 0x0B09, 0x121A, 0x0B11, 0x111A, 0x0B21, 0x109A,
151 0x0B41, 0x105A, 0x0B81, 0x103A, 0x0C07, 0x1C06, 0x0C0B, 0x1A06, 0x0C0D, 0x1606,
152 0x0C0E, 0x0E06, 0x0C13, 0x1906, 0x0C15, 0x1506, 0x0C16, 0x0D06, 0x0C19, 0x1306,
153 0x0C23, 0x1886, 0x0C25, 0x1486, 0x0C26, 0x0C86, 0x0C29, 0x1286, 0x0C31, 0x1186,
154 0x0C43, 0x1846, 0x0C45, 0x1446, 0x0C49, 0x1246, 0x0C51, 0x1146, 0x0C61, 0x10C6,
155 0x0C83, 0x1826, 0x0C85, 0x1426, 0x0C89, 0x1226, 0x0C91, 0x1126, 0x0CA1, 0x10A6,
156 0x0CC1, 0x1066, 0x0D03, 0x1816, 0x0D05, 0x1416, 0x0D09, 0x1216, 0x0D11, 0x1116,
157 0x0D21, 0x1096, 0x0D41, 0x1056, 0x0D81, 0x1036, 0x0E03, 0x180E, 0x0E05, 0x140E,
158 0x0E09, 0x120E, 0x0E11, 0x110E, 0x0E21, 0x108E, 0x0E41, 0x104E, 0x0E81, 0x102E,
159 0x0F01, 0x101E, 0x100F, 0x1E01, 0x1017, 0x1D01, 0x101B, 0x1B01, 0x101D, 0x1701,
160 0x1027, 0x1C81, 0x102B, 0x1A81, 0x102D, 0x1681, 0x1033, 0x1981, 0x1035, 0x1581,
161 0x1039, 0x1381, 0x1047, 0x1C41, 0x104B, 0x1A41, 0x104D, 0x1641, 0x1053, 0x1941,
162 0x1055, 0x1541, 0x1059, 0x1341, 0x1063, 0x18C1, 0x1065, 0x14C1, 0x1069, 0x12C1,
163 0x1071, 0x11C1, 0x1087, 0x1C21, 0x108B, 0x1A21, 0x108D, 0x1621, 0x1093, 0x1921,
164 0x1095, 0x1521, 0x1099, 0x1321, 0x10A3, 0x18A1, 0x10A5, 0x14A1, 0x10A9, 0x12A1,
165 0x10B1, 0x11A1, 0x10C3, 0x1861, 0x10C5, 0x1461, 0x10C9, 0x1261, 0x10D1, 0x1161,
166 0x1107, 0x1C11, 0x110B, 0x1A11, 0x110D, 0x1611, 0x1113, 0x1911, 0x1115, 0x1511,
167 0x1119, 0x1311, 0x1123, 0x1891, 0x1125, 0x1491, 0x1129, 0x1291, 0x1131, 0x1191,
168 0x1143, 0x1851, 0x1145, 0x1451, 0x1149, 0x1251, 0x1183, 0x1831, 0x1185, 0x1431,
169 0x1189, 0x1231, 0x1207, 0x1C09, 0x120B, 0x1A09, 0x120D, 0x1609, 0x1213, 0x1909,
170 0x1215, 0x1509, 0x1219, 0x1309, 0x1223, 0x1889, 0x1225, 0x1489, 0x1229, 0x1289,
171 0x1243, 0x1849, 0x1245, 0x1449, 0x1283, 0x1829, 0x1285, 0x1429, 0x1303, 0x1819,
172 0x1305, 0x1419, 0x1407, 0x1C05, 0x140B, 0x1A05, 0x140D, 0x1605, 0x1413, 0x1905,
173 0x1415, 0x1505, 0x1423, 0x1885, 0x1425, 0x1485, 0x1443, 0x1845, 0x1483, 0x1825,
174 0x1503, 0x1815, 0x1603, 0x180D, 0x1807, 0x1C03, 0x180B, 0x1A03, 0x1813, 0x1903,
175 0x1823, 0x1883, 0x1843, 0x1445, 0x1249, 0x1151, 0x10E1, 0x0C46, 0x0A4A, 0x0952,
176 0x08E2, 0x064C, 0x0554, 0x04E4, 0x0358, 0x02E8, 0x01F0
177 };
178
179 static const unsigned short AppxD_II[78] = {
180 /* Appendix D Table II - 2 of 13 characters */
181 0x0003, 0x1800, 0x0005, 0x1400, 0x0006, 0x0C00, 0x0009, 0x1200, 0x000A, 0x0A00,
182 0x000C, 0x0600, 0x0011, 0x1100, 0x0012, 0x0900, 0x0014, 0x0500, 0x0018, 0x0300,
183 0x0021, 0x1080, 0x0022, 0x0880, 0x0024, 0x0480, 0x0028, 0x0280, 0x0030, 0x0180,
184 0x0041, 0x1040, 0x0042, 0x0840, 0x0044, 0x0440, 0x0048, 0x0240, 0x0050, 0x0140,
185 0x0060, 0x00C0, 0x0081, 0x1020, 0x0082, 0x0820, 0x0084, 0x0420, 0x0088, 0x0220,
186 0x0090, 0x0120, 0x0101, 0x1010, 0x0102, 0x0810, 0x0104, 0x0410, 0x0108, 0x0210,
187 0x0201, 0x1008, 0x0202, 0x0808, 0x0204, 0x0408, 0x0401, 0x1004, 0x0402, 0x0804,
188 0x0801, 0x1002, 0x1001, 0x0802, 0x0404, 0x0208, 0x0110, 0x00A0
189 };
190
191 static const unsigned short int AppxD_IV[130] = {
192 /* Appendix D Table IV - Bar-to-Character Mapping (reverse lookup) */
193 67, 6, 78, 16, 86, 95, 34, 40, 45, 113, 117, 121, 62, 87, 18, 104, 41, 76, 57, 119, 115, 72, 97,
194 2, 127, 26, 105, 35, 122, 52, 114, 7, 24, 82, 68, 63, 94, 44, 77, 112, 70, 100, 39, 30, 107,
195 15, 125, 85, 10, 65, 54, 88, 20, 106, 46, 66, 8, 116, 29, 61, 99, 80, 90, 37, 123, 51, 25, 84,
196 129, 56, 4, 109, 96, 28, 36, 47, 11, 71, 33, 102, 21, 9, 17, 49, 124, 79, 64, 91, 42, 69, 53,
197 60, 14, 1, 27, 103, 126, 75, 89, 50, 120, 19, 32, 110, 92, 111, 130, 59, 31, 12, 81, 43, 55,
198 5, 74, 22, 101, 128, 58, 118, 48, 108, 38, 98, 93, 23, 83, 13, 73, 3
199 };
200
201 /***************************************************************************
202 ** USPS_MSB_Math_CRC11GenerateFrameCheckSequence
203 **
204 ** Inputs:
205 ** ByteAttayPtr is the address of a 13 byte array holding 102 bytes which
206 ** are right justified - ie: the leftmost 2 bits of the first byte do not
207 ** hold data and must be set to zero.
208 **
209 ** Outputs:
210 ** return unsigned short - 11 bit Frame Check Sequence (right justified)
211 ***************************************************************************/
USPS_MSB_Math_CRC11GenerateFrameCheckSequence(unsigned char * ByteArrayPtr)212 extern unsigned short USPS_MSB_Math_CRC11GenerateFrameCheckSequence(unsigned char *ByteArrayPtr) {
213 unsigned short GeneratorPolynomial = 0x0F35;
214 unsigned short FrameCheckSequence = 0x07FF;
215 unsigned short Data;
216 int ByteIndex, Bit;
217
218 /* Do most significant byte skipping the 2 most significant bits */
219 Data = *ByteArrayPtr << 5;
220 ByteArrayPtr++;
221 for (Bit = 2; Bit < 8; Bit++) {
222 if ((FrameCheckSequence ^ Data) & 0x400)
223 FrameCheckSequence = (FrameCheckSequence << 1) ^ GeneratorPolynomial;
224 else
225 FrameCheckSequence = (FrameCheckSequence << 1);
226 FrameCheckSequence &= 0x7FF;
227 Data <<= 1;
228 }
229 /* Do rest of the bytes */
230 for (ByteIndex = 1; ByteIndex < 13; ByteIndex++) {
231 Data = *ByteArrayPtr << 3;
232 ByteArrayPtr++;
233 for (Bit = 0; Bit < 8; Bit++) {
234 if ((FrameCheckSequence ^ Data) & 0x0400) {
235 FrameCheckSequence = (FrameCheckSequence << 1) ^ GeneratorPolynomial;
236 } else {
237 FrameCheckSequence = (FrameCheckSequence << 1);
238 }
239 FrameCheckSequence &= 0x7FF;
240 Data <<= 1;
241 }
242 }
243 return FrameCheckSequence;
244 }
245
imail(struct zint_symbol * symbol,unsigned char source[],int length)246 int imail(struct zint_symbol *symbol, unsigned char source[], int length) {
247 char data_pattern[200];
248 int error_number;
249 int i, j, read;
250 char zip[35], tracker[35], zip_adder[11], temp[2];
251 short int accum[112], x_reg[112], y_reg[112];
252 unsigned char byte_array[13];
253 unsigned short usps_crc;
254 int codeword[10];
255 unsigned short characters[10];
256 short int bar_map[130];
257
258 error_number = 0;
259
260 if (length > 32) {
261 strcpy(symbol->errtxt, "450: Input too long");
262 return ZINT_ERROR_TOO_LONG;
263 }
264 error_number = is_sane(SODIUM, source, length);
265 if (error_number == ZINT_ERROR_INVALID_DATA) {
266 strcpy(symbol->errtxt, "451: Invalid characters in data");
267 return error_number;
268 }
269
270 strcpy(zip, "");
271 strcpy(tracker, "");
272
273 /* separate the tracking code from the routing code */
274
275 read = 0;
276 j = 0;
277 for (i = 0; i < length; i++) {
278 if (source[i] == '-') {
279 tracker[read] = '\0';
280 j = 1;
281 read = 0;
282 } else {
283 if (j == 0) {
284 /* reading tracker */
285 tracker[read] = source[i];
286 read++;
287 } else {
288 /* reading zip code */
289 zip[read] = source[i];
290 read++;
291 }
292 }
293 }
294 if (j == 0) {
295 tracker[read] = '\0';
296 } else {
297 zip[read] = '\0';
298 }
299
300 if (strlen(tracker) != 20) {
301 strcpy(symbol->errtxt, "452: Invalid length tracking code");
302 return ZINT_ERROR_INVALID_DATA;
303 }
304 if (strlen(zip) > 11) {
305 strcpy(symbol->errtxt, "453: Invalid ZIP code");
306 return ZINT_ERROR_INVALID_DATA;
307 }
308
309 /* *** Step 1 - Conversion of Data Fields into Binary Data *** */
310
311 /* Routing code first */
312
313 for (i = 0; i < 112; i++) {
314 accum[i] = 0;
315 }
316
317 for (read = 0; read < strlen(zip); read++) {
318
319 for (i = 0; i < 112; i++) {
320 x_reg[i] = accum[i];
321 }
322
323 for (i = 0; i < 9; i++) {
324 binary_add(accum, x_reg);
325 }
326
327 for (i = 0; i < 112; i++) {
328 x_reg[i] = 0;
329 }
330
331 for (i = 0; i < 4; i++) {
332 if (ctoi(zip[read]) & (0x01 << i)) x_reg[i] = 1;
333 }
334
335 binary_add(accum, x_reg);
336 }
337
338 /* add weight to routing code */
339
340 for (i = 0; i < 112; i++) {
341 x_reg[i] = accum[i];
342 }
343
344 if (strlen(zip) > 9) {
345 strcpy(zip_adder, "1000100001");
346 } else {
347 if (strlen(zip) > 5) {
348 strcpy(zip_adder, "100001");
349 } else {
350 if (strlen(zip) > 0) {
351 strcpy(zip_adder, "1");
352 } else {
353 strcpy(zip_adder, "0");
354 }
355 }
356 }
357
358 for (i = 0; i < 112; i++) {
359 accum[i] = 0;
360 }
361
362 for (read = 0; read < strlen(zip_adder); read++) {
363
364 for (i = 0; i < 112; i++) {
365 y_reg[i] = accum[i];
366 }
367
368 for (i = 0; i < 9; i++) {
369 binary_add(accum, y_reg);
370 }
371
372 for (i = 0; i < 112; i++) {
373 y_reg[i] = 0;
374 }
375
376 for (i = 0; i < 4; i++) {
377 if (ctoi(zip_adder[read]) & (0x01 << i)) y_reg[i] = 1;
378 }
379
380 binary_add(accum, y_reg);
381 }
382
383 binary_add(accum, x_reg);
384
385 /* tracking code */
386
387 /* multiply by 10 */
388 for (i = 0; i < 112; i++) {
389 y_reg[i] = accum[i];
390 }
391
392 for (i = 0; i < 9; i++) {
393 binary_add(accum, y_reg);
394 }
395
396 for (i = 0; i < 112; i++) {
397 y_reg[i] = 0;
398 }
399
400 /* add first digit of tracker */
401 for (i = 0; i < 4; i++) {
402 if (ctoi(tracker[0]) & (0x01 << i)) y_reg[i] = 1;
403 }
404
405 binary_add(accum, y_reg);
406
407 /* multiply by 5 */
408 for (i = 0; i < 112; i++) {
409 y_reg[i] = accum[i];
410 }
411
412 for (i = 0; i < 4; i++) {
413 binary_add(accum, y_reg);
414 }
415
416 for (i = 0; i < 112; i++) {
417 y_reg[i] = 0;
418 }
419
420 /* add second digit */
421 for (i = 0; i < 4; i++) {
422 if (ctoi(tracker[1]) & (0x01 << i)) y_reg[i] = 1;
423 }
424
425 binary_add(accum, y_reg);
426
427 /* and then the rest */
428
429 for (read = 2; read < strlen(tracker); read++) {
430
431 for (i = 0; i < 112; i++) {
432 y_reg[i] = accum[i];
433 }
434
435 for (i = 0; i < 9; i++) {
436 binary_add(accum, y_reg);
437 }
438
439 for (i = 0; i < 112; i++) {
440 y_reg[i] = 0;
441 }
442
443 for (i = 0; i < 4; i++) {
444 if (ctoi(tracker[read]) & (0x01 << i)) y_reg[i] = 1;
445 }
446
447 binary_add(accum, y_reg);
448 }
449
450 /* *** Step 2 - Generation of 11-bit CRC on Binary Data *** */
451
452 accum[103] = 0;
453 accum[102] = 0;
454
455 memset(byte_array, 0, 13);
456 for (j = 0; j < 13; j++) {
457 i = 96 - (8 * j);
458 byte_array[j] = 0;
459 byte_array[j] += accum[i];
460 byte_array[j] += 2 * accum[i + 1];
461 byte_array[j] += 4 * accum[i + 2];
462 byte_array[j] += 8 * accum[i + 3];
463 byte_array[j] += 16 * accum[i + 4];
464 byte_array[j] += 32 * accum[i + 5];
465 byte_array[j] += 64 * accum[i + 6];
466 byte_array[j] += 128 * accum[i + 7];
467 }
468
469 usps_crc = USPS_MSB_Math_CRC11GenerateFrameCheckSequence(byte_array);
470
471 /* *** Step 3 - Conversion from Binary Data to Codewords *** */
472
473 /* start with codeword J which is base 636 */
474 for (i = 0; i < 112; i++) {
475 x_reg[i] = 0;
476 y_reg[i] = 0;
477 }
478
479 x_reg[101] = 1;
480 x_reg[98] = 1;
481 x_reg[97] = 1;
482 x_reg[96] = 1;
483 x_reg[95] = 1;
484 x_reg[94] = 1;
485
486 for (i = 92; i >= 0; i--) {
487 y_reg[i] = islarger(accum, x_reg);
488 if (y_reg[i] == 1) {
489 binary_subtract(accum, x_reg);
490 }
491 shiftdown(x_reg);
492 }
493
494 codeword[9] = (accum[9] * 512) + (accum[8] * 256) + (accum[7] * 128) + (accum[6] * 64) +
495 (accum[5] * 32) + (accum[4] * 16) + (accum[3] * 8) + (accum[2] * 4) +
496 (accum[1] * 2) + accum[0];
497
498 /* then codewords I to B with base 1365 */
499
500 for (j = 8; j > 0; j--) {
501 for (i = 0; i < 112; i++) {
502 accum[i] = y_reg[i];
503 y_reg[i] = 0;
504 x_reg[i] = 0;
505 }
506 x_reg[101] = 1;
507 x_reg[99] = 1;
508 x_reg[97] = 1;
509 x_reg[95] = 1;
510 x_reg[93] = 1;
511 x_reg[91] = 1;
512 for (i = 91; i >= 0; i--) {
513 y_reg[i] = islarger(accum, x_reg);
514 if (y_reg[i] == 1) {
515 binary_subtract(accum, x_reg);
516 }
517 shiftdown(x_reg);
518 }
519
520 codeword[j] = (accum[10] * 1024) + (accum[9] * 512) + (accum[8] * 256) +
521 (accum[7] * 128) + (accum[6] * 64) + (accum[5] * 32) +
522 (accum[4] * 16) + (accum[3] * 8) + (accum[2] * 4) +
523 (accum[1] * 2) + accum[0];
524 }
525
526 codeword[0] = (y_reg[10] * 1024) + (y_reg[9] * 512) + (y_reg[8] * 256) +
527 (y_reg[7] * 128) + (y_reg[6] * 64) + (y_reg[5] * 32) +
528 (y_reg[4] * 16) + (y_reg[3] * 8) + (y_reg[2] * 4) +
529 (y_reg[1] * 2) + y_reg[0];
530
531 for (i = 0; i < 8; i++) {
532 if (codeword[i] == 1365) {
533 codeword[i] = 0;
534 codeword[i + 1]++;
535 }
536 }
537
538 /* *** Step 4 - Inserting Additional Information into Codewords *** */
539
540 codeword[9] = codeword[9] * 2;
541
542 if (usps_crc >= 1024) {
543 codeword[0] += 659;
544 }
545
546 /* *** Step 5 - Conversion from Codewords to Characters *** */
547
548 for (i = 0; i < 10; i++) {
549 if (codeword[i] < 1287) {
550 characters[i] = AppxD_I[codeword[i]];
551 } else {
552 characters[i] = AppxD_II[codeword[i] - 1287];
553 }
554 }
555
556 for (i = 0; i < 10; i++) {
557 if (usps_crc & (1 << i)) {
558 characters[i] = 0x1FFF - characters[i];
559 }
560 }
561
562 /* *** Step 6 - Conversion from Characters to the Intelligent Mail Barcode *** */
563 for (i = 0; i < 10; i++) {
564 for (j = 0; j < 13; j++) {
565 if (characters[i] & (1 << j)) {
566 bar_map[AppxD_IV[(13 * i) + j] - 1] = 1;
567 } else {
568 bar_map[AppxD_IV[(13 * i) + j] - 1] = 0;
569 }
570 }
571 }
572
573 strcpy(data_pattern, "");
574 temp[1] = '\0';
575 for (i = 0; i < 65; i++) {
576 j = 0;
577 if (bar_map[i] == 0)
578 j += 1;
579 if (bar_map[i + 65] == 0)
580 j += 2;
581 temp[0] = itoc(j);
582 strcat(data_pattern, temp);
583 }
584
585 /* Translate 4-state data pattern to symbol */
586 read = 0;
587 for (i = 0; i < strlen(data_pattern); i++) {
588 if ((data_pattern[i] == '1') || (data_pattern[i] == '0')) {
589 set_module(symbol, 0, read);
590 }
591 set_module(symbol, 1, read);
592 if ((data_pattern[i] == '2') || (data_pattern[i] == '0')) {
593 set_module(symbol, 2, read);
594 }
595 read += 2;
596 }
597
598 symbol->row_height[0] = 3;
599 symbol->row_height[1] = 2;
600 symbol->row_height[2] = 3;
601
602 symbol->rows = 3;
603 symbol->width = read - 1;
604 return error_number;
605 }
606