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