1*f5736e95SDavid du Colombier /*
2*f5736e95SDavid du Colombier * asc85enc.c
3*f5736e95SDavid du Colombier * Copyright (C) 2000-2003 A.J. van Os; Released under GPL
4*f5736e95SDavid du Colombier *
5*f5736e95SDavid du Colombier * Description:
6*f5736e95SDavid du Colombier * Functions to for ASCII 85 encoding
7*f5736e95SDavid du Colombier *
8*f5736e95SDavid du Colombier *====================================================================
9*f5736e95SDavid du Colombier * This part of the software is based on:
10*f5736e95SDavid du Colombier * asc85ec.c - ASCII85 and Hex encoding for PostScript Level 2 and PDF
11*f5736e95SDavid du Colombier * Copyright (C) 1994-99 Thomas Merz (tm@muc.de)
12*f5736e95SDavid du Colombier *====================================================================
13*f5736e95SDavid du Colombier * The credit should go to him, but all the bugs are mine.
14*f5736e95SDavid du Colombier */
15*f5736e95SDavid du Colombier
16*f5736e95SDavid du Colombier #include <stdio.h>
17*f5736e95SDavid du Colombier #include "antiword.h"
18*f5736e95SDavid du Colombier
19*f5736e95SDavid du Colombier static const ULONG aulPower85[5] = {
20*f5736e95SDavid du Colombier 1UL, 85UL, 85UL * 85, 85UL * 85 * 85, 85UL * 85 * 85 * 85,
21*f5736e95SDavid du Colombier };
22*f5736e95SDavid du Colombier static int iOutBytes = 0; /* Number of characters in an output line */
23*f5736e95SDavid du Colombier static char cCharPrev = '\0';
24*f5736e95SDavid du Colombier
25*f5736e95SDavid du Colombier /*
26*f5736e95SDavid du Colombier * Two percent characters at the start of a line will cause trouble
27*f5736e95SDavid du Colombier * with some post-processing software. In order to avoid this, we
28*f5736e95SDavid du Colombier * simply insert a line break if we encounter two percent characters
29*f5736e95SDavid du Colombier * at the start of the line. Of course, this rather simplistic
30*f5736e95SDavid du Colombier * algorithm may lead to a large line count in pathological cases,
31*f5736e95SDavid du Colombier * but the chance for hitting such a case is very small, and even
32*f5736e95SDavid du Colombier * so it's only a cosmetic flaw and not a functional restriction.
33*f5736e95SDavid du Colombier */
34*f5736e95SDavid du Colombier
35*f5736e95SDavid du Colombier /*
36*f5736e95SDavid du Colombier * vOutputByte - output one byte
37*f5736e95SDavid du Colombier */
38*f5736e95SDavid du Colombier static void
vOutputByte(ULONG ulChar,FILE * pOutFile)39*f5736e95SDavid du Colombier vOutputByte(ULONG ulChar, FILE *pOutFile)
40*f5736e95SDavid du Colombier {
41*f5736e95SDavid du Colombier if (iOutBytes == 1 && cCharPrev == '%' && ulChar == (ULONG)'%') {
42*f5736e95SDavid du Colombier if (putc('\n', pOutFile) != EOF) {
43*f5736e95SDavid du Colombier iOutBytes = 0;
44*f5736e95SDavid du Colombier }
45*f5736e95SDavid du Colombier }
46*f5736e95SDavid du Colombier if (putc((int)ulChar, pOutFile) == EOF) {
47*f5736e95SDavid du Colombier return;
48*f5736e95SDavid du Colombier }
49*f5736e95SDavid du Colombier iOutBytes++;
50*f5736e95SDavid du Colombier if (iOutBytes > 63) {
51*f5736e95SDavid du Colombier if (putc('\n', pOutFile) != EOF) {
52*f5736e95SDavid du Colombier iOutBytes = 0;
53*f5736e95SDavid du Colombier }
54*f5736e95SDavid du Colombier }
55*f5736e95SDavid du Colombier cCharPrev = (char)ulChar;
56*f5736e95SDavid du Colombier } /* end of vOutputByte */
57*f5736e95SDavid du Colombier
58*f5736e95SDavid du Colombier /*
59*f5736e95SDavid du Colombier * vASCII85EncodeByte - ASCII 85 encode a byte
60*f5736e95SDavid du Colombier */
61*f5736e95SDavid du Colombier void
vASCII85EncodeByte(FILE * pOutFile,int iByte)62*f5736e95SDavid du Colombier vASCII85EncodeByte(FILE *pOutFile, int iByte)
63*f5736e95SDavid du Colombier {
64*f5736e95SDavid du Colombier static ULONG ulBuffer[4] = { 0, 0, 0, 0 };
65*f5736e95SDavid du Colombier static int iInBuffer = 0;
66*f5736e95SDavid du Colombier ULONG ulValue, ulTmp;
67*f5736e95SDavid du Colombier int iIndex;
68*f5736e95SDavid du Colombier
69*f5736e95SDavid du Colombier fail(pOutFile == NULL);
70*f5736e95SDavid du Colombier fail(iInBuffer < 0);
71*f5736e95SDavid du Colombier fail(iInBuffer > 3);
72*f5736e95SDavid du Colombier
73*f5736e95SDavid du Colombier if (iByte == EOF) {
74*f5736e95SDavid du Colombier /* End Of File, time to clean up */
75*f5736e95SDavid du Colombier if (iInBuffer > 0 && iInBuffer < 4) {
76*f5736e95SDavid du Colombier /* Encode the remaining bytes */
77*f5736e95SDavid du Colombier ulValue = 0;
78*f5736e95SDavid du Colombier for (iIndex = iInBuffer - 1; iIndex >= 0; iIndex--) {
79*f5736e95SDavid du Colombier ulValue |=
80*f5736e95SDavid du Colombier ulBuffer[iIndex] << (8 * (3 - iIndex));
81*f5736e95SDavid du Colombier }
82*f5736e95SDavid du Colombier for (iIndex = 4; iIndex >= 4 - iInBuffer; iIndex--) {
83*f5736e95SDavid du Colombier ulTmp = ulValue / aulPower85[iIndex];
84*f5736e95SDavid du Colombier vOutputByte(ulTmp + '!', pOutFile);
85*f5736e95SDavid du Colombier ulValue -= ulTmp * aulPower85[iIndex];
86*f5736e95SDavid du Colombier }
87*f5736e95SDavid du Colombier }
88*f5736e95SDavid du Colombier /* Add the End Of Data marker */
89*f5736e95SDavid du Colombier (void)putc('~', pOutFile);
90*f5736e95SDavid du Colombier (void)putc('>', pOutFile);
91*f5736e95SDavid du Colombier (void)putc('\n', pOutFile);
92*f5736e95SDavid du Colombier /* Reset the control variables */
93*f5736e95SDavid du Colombier iInBuffer = 0;
94*f5736e95SDavid du Colombier iOutBytes = 0;
95*f5736e95SDavid du Colombier cCharPrev = '\0';
96*f5736e95SDavid du Colombier return;
97*f5736e95SDavid du Colombier }
98*f5736e95SDavid du Colombier
99*f5736e95SDavid du Colombier ulBuffer[iInBuffer] = (ULONG)iByte & 0xff;
100*f5736e95SDavid du Colombier iInBuffer++;
101*f5736e95SDavid du Colombier
102*f5736e95SDavid du Colombier if (iInBuffer >= 4) {
103*f5736e95SDavid du Colombier ulValue = (ulBuffer[0] << 24) | (ulBuffer[1] << 16) |
104*f5736e95SDavid du Colombier (ulBuffer[2] << 8) | ulBuffer[3];
105*f5736e95SDavid du Colombier if (ulValue == 0) {
106*f5736e95SDavid du Colombier vOutputByte((ULONG)'z', pOutFile); /* Shortcut for 0 */
107*f5736e95SDavid du Colombier } else {
108*f5736e95SDavid du Colombier for (iIndex = 4; iIndex >= 0; iIndex--) {
109*f5736e95SDavid du Colombier ulTmp = ulValue / aulPower85[iIndex];
110*f5736e95SDavid du Colombier vOutputByte(ulTmp + '!', pOutFile);
111*f5736e95SDavid du Colombier ulValue -= ulTmp * aulPower85[iIndex];
112*f5736e95SDavid du Colombier }
113*f5736e95SDavid du Colombier }
114*f5736e95SDavid du Colombier /* Reset the buffer */
115*f5736e95SDavid du Colombier iInBuffer = 0;
116*f5736e95SDavid du Colombier }
117*f5736e95SDavid du Colombier } /* end of vASCII85EncodeByte */
118*f5736e95SDavid du Colombier
119*f5736e95SDavid du Colombier /*
120*f5736e95SDavid du Colombier * vASCII85EncodeArray - ASCII 85 encode a byte array
121*f5736e95SDavid du Colombier */
122*f5736e95SDavid du Colombier void
vASCII85EncodeArray(FILE * pInFile,FILE * pOutFile,size_t tLength)123*f5736e95SDavid du Colombier vASCII85EncodeArray(FILE *pInFile, FILE *pOutFile, size_t tLength)
124*f5736e95SDavid du Colombier {
125*f5736e95SDavid du Colombier size_t tCount;
126*f5736e95SDavid du Colombier int iByte;
127*f5736e95SDavid du Colombier
128*f5736e95SDavid du Colombier fail(pInFile == NULL);
129*f5736e95SDavid du Colombier fail(pOutFile == NULL);
130*f5736e95SDavid du Colombier
131*f5736e95SDavid du Colombier DBG_DEC(tLength);
132*f5736e95SDavid du Colombier
133*f5736e95SDavid du Colombier for (tCount = 0; tCount < tLength; tCount++) {
134*f5736e95SDavid du Colombier iByte = iNextByte(pInFile);
135*f5736e95SDavid du Colombier if (iByte == EOF) {
136*f5736e95SDavid du Colombier break;
137*f5736e95SDavid du Colombier }
138*f5736e95SDavid du Colombier vASCII85EncodeByte(pOutFile, iByte);
139*f5736e95SDavid du Colombier }
140*f5736e95SDavid du Colombier } /* end of vASCII85EncodeArray */
141*f5736e95SDavid du Colombier
142*f5736e95SDavid du Colombier /*
143*f5736e95SDavid du Colombier * vASCII85EncodeFile - ASCII 85 encode part of a file
144*f5736e95SDavid du Colombier */
145*f5736e95SDavid du Colombier void
vASCII85EncodeFile(FILE * pInFile,FILE * pOutFile,size_t tLength)146*f5736e95SDavid du Colombier vASCII85EncodeFile(FILE *pInFile, FILE *pOutFile, size_t tLength)
147*f5736e95SDavid du Colombier {
148*f5736e95SDavid du Colombier fail(pInFile == NULL);
149*f5736e95SDavid du Colombier fail(pOutFile == NULL);
150*f5736e95SDavid du Colombier fail(tLength == 0);
151*f5736e95SDavid du Colombier
152*f5736e95SDavid du Colombier vASCII85EncodeArray(pInFile, pOutFile, tLength);
153*f5736e95SDavid du Colombier vASCII85EncodeByte(pOutFile, EOF);
154*f5736e95SDavid du Colombier } /* end of vASCII85EncodeFile */
155