1 /*	$Id$ */
2 /*
3  * Copyright (c) 1990-1996 Sam Leffler
4  * Copyright (c) 1991-1996 Silicon Graphics, Inc.
5  * HylaFAX is a trademark of Silicon Graphics
6  *
7  * Permission to use, copy, modify, distribute, and sell this software and
8  * its documentation for any purpose is hereby granted without fee, provided
9  * that (i) the above copyright notices and this permission notice appear in
10  * all copies of the software and related documentation, and (ii) the names of
11  * Sam Leffler and Silicon Graphics may not be used in any advertising or
12  * publicity relating to the software without the specific, prior written
13  * permission of Sam Leffler and Silicon Graphics.
14  *
15  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
17  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
18  *
19  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
20  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
21  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
22  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
23  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24  * OF THIS SOFTWARE.
25  */
26 #include <ctype.h>
27 #include <stdlib.h>
28 
29 #include "ClassModem.h"
30 #include "FaxServer.h"
31 #include "FaxTrace.h"
32 #include "FaxFont.h"
33 #include "t.30.h"
34 #include "Sys.h"
35 #include "SystemLog.h"
36 
FaxModem(FaxServer & s,const ModemConfig & c)37 FaxModem::FaxModem(FaxServer& s, const ModemConfig& c)
38     : ClassModem(s,c)
39     , server(s)
40 {
41     tagLineFont = NULL;
42     minsp = BR_2400;
43     curreq = NULL;
44     group3opts = 0;
45     imagefd = 0;
46     // fill order settings may be overwritten in derived class
47     recvFillOrder = (conf.recvFillOrder != 0)? conf.recvFillOrder : FILLORDER_LSB2MSB;
48     sendFillOrder = (conf.sendFillOrder != 0)? conf.sendFillOrder : FILLORDER_LSB2MSB;
49     rtcRev        = TIFFGetBitRevTable(sendFillOrder != FILLORDER_LSB2MSB);
50 }
51 
~FaxModem()52 FaxModem::~FaxModem()
53 {
54     delete tagLineFont;
55 }
56 
57 /*
58  * Default methods for modem driver interface.
59  */
60 
getTagLineSlop() const61 u_int FaxModem::getTagLineSlop() const		{ return tagLineSlop; }
62 
63 /*
64  * Do setup work prior to placing the call.
65  */
66 bool
sendSetup(FaxRequest & req,const Class2Params &,Status &)67 FaxModem::sendSetup(FaxRequest& req, const Class2Params&, Status&)
68 {
69     minsp = fxmax((u_int) req.minbr, fxmax((u_int) conf.minSpeed, modemParams.getMinSpeed()));
70     pageNumber = 1;
71     pageNumberOfJob = req.npages + 1;
72     pageNumberCovered = pageNumberSkipped = 0;
73     if (conf.tagLineCoverNumString.length() )
74 	    pageNumberOfJob -= req.ncover;
75     if (! conf.countSkippedPages)
76 	    pageNumberOfJob -= req.nskip;
77     if (conf.useJobTagLine && req.desiredtl != 0)
78 	setupTagLine(req, req.tagline);
79     else
80 	setupTagLine(req, conf.tagLineFmt);
81     curreq = &req;
82     return (true);
83 }
84 /*
85  * Do work at the beginning of a send operation;
86  * after a call has been established.
87  */
88 void
sendBegin()89 FaxModem::sendBegin()
90 {
91     if (conf.sendBeginCmd != "")
92 	atCmd(conf.sendBeginCmd);
93     optFrames = 0;
94 }
sendSetupPhaseB(const fxStr &,const fxStr &)95 void FaxModem::sendSetupPhaseB(const fxStr&, const fxStr&){}
sendEnd()96 void FaxModem::sendEnd()	{}
97 
98 bool
recvBegin(Status &)99 FaxModem::recvBegin(Status&)
100 {
101     optFrames = 0;
102     return (true);
103 }
104 
105 bool
recvEOMBegin(Status &)106 FaxModem::recvEOMBegin(Status&)
107 {
108     optFrames = 0;
109     return (true);
110 }
111 
112 bool
pollBegin(const fxStr &,const fxStr &,const fxStr &,Status &)113 FaxModem::pollBegin(const fxStr&, const fxStr&, const fxStr&, Status&)
114 {
115     optFrames = 0;
116     return (true);
117 }
118 
119 /*
120  * Issue a command upon successful reception.
121  */
122 void
recvSucceeded()123 FaxModem::recvSucceeded()
124 {
125     if (conf.recvSuccessCmd != "")
126 	atCmd(conf.recvSuccessCmd, AT_OK);
127 }
128 
129 static void
stripBlanks(fxStr & d,const fxStr & s)130 stripBlanks(fxStr& d, const fxStr& s)
131 {
132     d = s;
133     d.remove(0, d.skip(0,' '));		// strip leading white space
134     u_int pos = d.skipR(d.length(),' ');
135     d.remove(pos, d.length() - pos);	// and trailing white space
136 }
137 
138 void
recvTSI(const fxStr & s)139 FaxModem::recvTSI(const fxStr& s)
140 {
141     stripBlanks(tsi, s);
142     protoTrace("REMOTE TSI \"%s\"", (const char*) tsi);
143     optFrames |= 0x1;
144 }
145 void
recvCSI(const fxStr & s)146 FaxModem::recvCSI(const fxStr& s)
147 {
148     stripBlanks(tsi, s);
149     protoTrace("REMOTE CSI \"%s\"", (const char*) tsi);
150     optFrames |= 0x1;
151 }
152 bool
getRecvTSI(fxStr & s)153 FaxModem::getRecvTSI(fxStr& s)
154 {
155     if (optFrames & 0x1) {
156 	s = tsi;
157 	return (true);
158     } else
159 	return (false);
160 }
getSendCSI(fxStr & s)161 bool FaxModem::getSendCSI(fxStr& s)	{ return getRecvTSI(s); }
162 
163 void
recvPWD(const fxStr & s)164 FaxModem::recvPWD(const fxStr& s)
165 {
166     stripBlanks(pwd, s);
167     protoTrace("REMOTE PWD \"%s\"", (const char*) pwd);
168     optFrames |= 0x2;
169 }
170 bool
getRecvPWD(fxStr & s)171 FaxModem::getRecvPWD(fxStr& s)
172 {
173     if (optFrames & 0x2) {
174 	s = pwd;
175 	return (true);
176     } else
177 	return (false);
178 }
179 void
recvSUB(const fxStr & s)180 FaxModem::recvSUB(const fxStr& s)
181 {
182     stripBlanks(sub, s);
183     protoTrace("REMOTE SUB \"%s\"", (const char*) sub);
184     optFrames |= 0x4;
185 }
186 bool
getRecvSUB(fxStr & s)187 FaxModem::getRecvSUB(fxStr& s)
188 {
189     if (optFrames & 0x4) {
190 	s = sub;
191 	return (true);
192     } else
193 	return (false);
194 }
195 
196 void
recvNSF(const NSF & aNsf)197 FaxModem::recvNSF( const NSF& aNsf )
198 {
199     nsf = aNsf;
200     optFrames |= 0x8;
201     protoTrace("REMOTE NSF \"%s\"", (const char*) nsf.getHexNsf() );
202     protoTrace("NSF remote fax equipment: %s %s",
203                (const char*)nsf.getVendor(),
204                (const char*)nsf.getModel());
205     if( nsf.stationIdFound() )
206         protoTrace("NSF %sremote station ID: \"%s\"",
207                    nsf.vendorFound()? "": "possible ",
208                    nsf.getStationId());
209 }
210 
211 bool
getSendNSF(NSF & aNsf)212 FaxModem::getSendNSF(NSF& aNsf)
213 {
214     if (optFrames & 0x8) {
215         aNsf = nsf;
216         return (true);
217     } else {
218         return (false);
219     }
220 }
221 
222 void
recvDCS(const Class2Params & params)223 FaxModem::recvDCS(const Class2Params& params)
224 {
225     protoTrace("REMOTE wants %s", params.bitRateName());
226     protoTrace("REMOTE wants %s", params.pageWidthName());
227     protoTrace("REMOTE wants %s", params.pageLengthName());
228     protoTrace("REMOTE wants %s", params.verticalResName());
229     protoTrace("REMOTE wants %s", params.dataFormatName());
230     if (params.ec != EC_DISABLE)
231 	protoTrace("REMOTE wants %s", params.ecmName());
232 }
getRecvParams() const233 const Class2Params& FaxModem::getRecvParams() const	{ return params; }
234 
235 /*
236  * Decode the post-page-handling string to get page
237  * chopping information for the current page.  The
238  * page chop information is optional and always
239  * precedes the page-handling information, so at least
240  * 2+5+1 characters must be present.  The format of the
241  * information is:
242  *
243  *   xxZcccxM
244  *
245  * xx is the hex-encoded session parameters (see below),
246  * M is a post-page message, and cccc is an optional 4-digit
247  * hex encoding of the number of bytes to chop from the
248  * encoded page data.  Note also that we only return the
249  * chop count if the negotiated session parameters permit
250  * us to send a variable-length page.
251  */
252 u_int
decodePageChop(const fxStr & pph,const Class2Params & params)253 FaxModem::decodePageChop(const fxStr& pph, const Class2Params& params)
254 {
255     if (params.ln == LN_INF && pph.length() >= 2+5+1 && pph[2] == 'Z') {
256 	char buf[5];
257 	buf[0] = pph[2+1];
258 	buf[1] = pph[2+2];
259 	buf[2] = pph[2+3];
260 	buf[3] = pph[2+4];
261 	buf[4] = '\0';
262 	return ((u_int) strtoul(buf, NULL, 16));
263     } else
264 	return (0);
265 }
266 
267 /*
268  * Decode the post-page-handling string to get the next
269  * post-page message.  The string is assumed to have 3
270  * characters per page of the form:
271  *
272  *   xxM
273  *
274  * where xx is a 2-digit hex encoding of the session
275  * parameters required to send the page data and the M
276  * the post-page message to use between this page and
277  * the next page.  See faxQueueApp::preparePageHandling
278  * for the construction of this string.
279  */
280 bool
decodePPM(const fxStr & pph,u_int & ppm,Status & eresult)281 FaxModem::decodePPM(const fxStr& pph, u_int& ppm, Status& eresult)
282 {
283     const char* what;
284     if (pph.length() >= 3 && (pph[2] != 'Z' || pph.length() >= 2+5+1)) {
285 	switch (pph[pph[2] == 'Z' ? 2+5 : 2+0]) {
286 	case 'P': ppm = PPM_EOP; return (true);
287 	case 'M': ppm = PPM_EOM; return (true);
288 	case 'S': ppm = PPM_MPS; return (true);
289 	case 'X': ppm = PPH_SKIP; return (true);
290 	}
291 	what = "unknown";
292     } else
293 	what = "bad";
294     eresult = Status(303, "Internal botch; %s post-page handling string \"%s\"",
295 	what, (const char*) pph);
296     return (false);
297 }
298 
299 /*
300  * Modem capability (and related) query interfaces.
301  */
302 
303 u_int
getCapabilities() const304 FaxModem::getCapabilities() const
305 {
306     return modemParams.encodeCaps();
307 }
308 
309 static u_int
bestBit(u_int bits,u_int top,u_int bot)310 bestBit(u_int bits, u_int top, u_int bot)
311 {
312     while (top > bot && (bits & BIT(top)) == 0)
313 	top--;
314     return (top);
315 }
316 
317 /*
318  * Return Class 2 code for best modem signalling rate.
319  */
320 u_int
getBestSignallingRate() const321 FaxModem::getBestSignallingRate() const
322 {
323     return bestBit(modemParams.br, BR_33600, BR_2400);
324 }
325 
326 /*
327  * Compare the requested signalling rate against
328  * those the modem can do and return the appropriate
329  * Class 2 bit rate code.
330  */
331 int
selectSignallingRate(int br) const332 FaxModem::selectSignallingRate(int br) const
333 {
334     for (; br >= 0 && (modemParams.br & BIT(br)) == 0; br--)
335 	;
336     return (br);
337 }
338 
339 /*
340  * Compare the requested min scanline time
341  * to what the modem can do and return the
342  * lowest time the modem can do.
343  */
344 int
selectScanlineTime(int st) const345 FaxModem::selectScanlineTime(int st) const
346 {
347     for (; st < ST_40MS && (modemParams.st & BIT(st)) == 0; st++)
348 	;
349     return (st);
350 }
351 
352 /*
353  * Return the best min scanline time the modem
354  * is capable of supporting.
355  */
356 u_int
getBestScanlineTime() const357 FaxModem::getBestScanlineTime() const
358 {
359     u_int st;
360     for (st = ST_0MS; st < ST_40MS; st++)
361 	if (modemParams.st & BIT(st))
362 	    break;
363     return st;
364 }
365 
366 /*
367  * Return the best vres the modem supports.
368  */
369 u_int
getVRes() const370 FaxModem::getVRes() const
371 {
372     /*
373      * We don't use bestBit() here because T.32 Table 21
374      * states that VR is to be reported as a bitmask
375      * of supported resolutions.  So we already have it.
376      */
377     return (modemParams.vr);
378 }
379 
380 /*
381  * Return the best page width the modem supports.
382  */
383 u_int
getBestPageWidth() const384 FaxModem::getBestPageWidth() const
385 {
386     // XXX NB: we don't use anything > WD_A3
387     return bestBit(modemParams.wd, WD_A3, WD_A4);
388 }
389 
390 /*
391  * Return the best page length the modem supports.
392  */
393 u_int
getBestPageLength() const394 FaxModem::getBestPageLength() const
395 {
396     return bestBit(modemParams.ln, LN_INF, LN_A4);
397 }
398 
399 /*
400  * Return the best data format the modem supports.
401  */
402 u_int
getBestDataFormat() const403 FaxModem::getBestDataFormat() const
404 {
405     return bestBit(modemParams.df, DF_JBIG, DF_1DMH);
406 }
407 
408 /*
409  * Return the best ECM functionality the modem supports.
410  */
411 u_int
getBestECM() const412 FaxModem::getBestECM() const
413 {
414     return bestBit(modemParams.ec, EC_ECLFULL, EC_DISABLE);
415 }
416 
417 /*
418  * Return whether or not the modem supports 2DMR.
419  */
420 bool
supports2D() const421 FaxModem::supports2D() const
422 {
423     return (modemParams.df & BIT(DF_2DMR)) != 0;
424 }
425 
426 /*
427  * Return whether or not the modem supports 2DMMR.
428  */
429 bool
supportsMMR() const430 FaxModem::supportsMMR() const
431 {
432     return (modemParams.df & BIT(DF_2DMMR)) != 0;
433 }
434 
435 /*
436  * Return whether or not the modem supports JBIG.
437  */
438 bool
supportsJBIG() const439 FaxModem::supportsJBIG() const
440 {
441     return (modemParams.df & BIT(DF_JBIG)) != 0;
442 }
443 
444 /*
445  * Return whether or not received EOLs are byte aligned.
446  */
447 bool
supportsEOLPadding() const448 FaxModem::supportsEOLPadding() const
449 {
450     return false;
451 }
452 
453 /*
454  * Return whether or not the modem is capable of polling.
455  */
456 bool
supportsPolling() const457 FaxModem::supportsPolling() const
458 {
459     return false;
460 }
461 
462 /*
463  * Return whether or not the modem supports
464  * the optional Error Correction Mode (ECM).
465  */
466 bool
supportsECM(u_int ec) const467 FaxModem::supportsECM(u_int ec) const
468 {
469     if (ec)
470 	return (modemParams.ec & BIT(ec)) != 0;
471     else	// supports "any ecm"
472 	return (modemParams.ec &~ BIT(EC_DISABLE)) != 0;
473 }
474 
475 /*
476  * Return whether or not the modem supports the
477  * specified vertical resolution.  Note that we're
478  * rather tolerant because of potential precision
479  * problems and general sloppiness on the part of
480  * applications writing TIFF files.
481  *
482  * Because R8 and R16 vertical resolutions are the same
483  * but differ by horizontal resolution, R16 is "coded"
484  * as "20" in order to support it.
485  */
486 bool
supportsVRes(float res) const487 FaxModem::supportsVRes(float res) const
488 {
489     if (3.0 <= res && res < 4.75)
490 	return ((modemParams.vr & VR_NORMAL) || (modemParams.vr & VR_200X100)) != 0;
491     else if (5.9 <= res && res < 9.8)
492 	return ((modemParams.vr & VR_FINE) || (modemParams.vr & VR_200X200)) != 0;
493     else if (9.8 <= res && res < 13)
494 	return (modemParams.vr & VR_300X300) != 0;
495     else if (13 <= res && res < 19)
496 	return ((modemParams.vr & VR_R8) || (modemParams.vr & VR_200X400)) != 0;
497     else if (res == 20)
498 	return (modemParams.vr & VR_R16) != 0;
499     else
500 	return false;
501 }
502 
503 /*
504  * Return whether or not the modem supports the
505  * specified page width.
506  */
507 bool
supportsPageWidth(u_int w,u_int r) const508 FaxModem::supportsPageWidth(u_int w, u_int r) const
509 {
510     switch (r) {
511 	case VR_R16:
512 	    switch (w) {
513 		case 3456:   return (modemParams.wd & BIT(WD_A4)) != 0;
514 		case 4096:   return (modemParams.wd & BIT(WD_B4)) != 0;
515 		case 4864:   return (modemParams.wd & BIT(WD_A3)) != 0;
516 	    }
517 	case VR_300X300:
518 	    switch (w) {
519 		case 2592:   return (modemParams.wd & BIT(WD_A4)) != 0;
520 		case 3072:   return (modemParams.wd & BIT(WD_B4)) != 0;
521 		case 3648:   return (modemParams.wd & BIT(WD_A3)) != 0;
522 	    }
523 	case VR_NORMAL:
524 	case VR_FINE:
525 	case VR_R8:
526 	case VR_200X100:
527 	case VR_200X200:
528 	case VR_200X400:
529 	    switch (w) {
530 		case 1728:   return (modemParams.wd & BIT(WD_A4)) != 0;
531 		case 2048:   return (modemParams.wd & BIT(WD_B4)) != 0;
532 		case 2432:   return (modemParams.wd & BIT(WD_A3)) != 0;
533 	    }
534     }
535     return false;
536 }
537 
538 /*
539  * Return whether or not the modem supports the
540  * specified page length.  As above for vertical
541  * resolution we're lenient in what we accept.
542  */
543 bool
supportsPageLength(u_int l) const544 FaxModem::supportsPageLength(u_int l) const
545 {
546     // XXX probably need to be more forgiving with values
547     if (270 < l && l <= 330)
548 	return (modemParams.ln & (BIT(LN_A4)|BIT(LN_INF))) != 0;
549     else if (330 < l && l <= 390)
550 	return (modemParams.ln & (BIT(LN_B4)|BIT(LN_INF))) != 0;
551     else
552 	return (modemParams.ln & BIT(LN_INF)) != 0;
553 }
554 
555 /*
556  * Return modems best capabilities for setting up
557  * the initial T.30 DIS when receiving data.
558  */
559 FaxParams
modemDIS() const560 FaxModem::modemDIS() const
561 {
562     Class2Params tmp(modemParams);
563     tmp.update(true);
564     return tmp;
565 }
566 
567 /*
568  * Tracing support.
569  */
570 
571 /*
572  * Trace a modem's capabilities.
573  */
574 void
traceModemParams()575 FaxModem::traceModemParams()
576 {
577     traceBitMask(modemParams.vr, Class2Params::verticalResNames);
578     traceBits(modemParams.br, Class2Params::bitRateNames);
579     traceBits(modemParams.wd, Class2Params::pageWidthNames);
580     traceBits(modemParams.ln, Class2Params::pageLengthNames);
581     u_int dataforms = modemParams.df + ((modemParams.jp & (BIT(JP_GREY) | BIT(JP_COLOR))) << 4);
582     traceBits(dataforms, Class2Params::dataFormatNames);
583     if (supportsECM())
584 	traceBits(modemParams.ec, Class2Params::ecmNames);
585     if (modemParams.bf & BIT(BF_ENABLE))
586 	modemSupports("binary file transfer");
587     traceBits(modemParams.st, Class2Params::scanlineTimeNames);
588 }
589 
590 void
traceFCF(const char * dir,u_int fcf)591 FaxModem::traceFCF(const char* dir, u_int fcf)
592 {
593     const char* fcfname;
594     switch (fcf & 0x7F) {
595 	case 0x00:
596 	    fcfname = "NULL (more blocks, same page)";
597 	    break;
598 	case FCF_DIS:
599 	    fcfname = "DIS (identification signal)";
600 	    break;
601 	case FCF_DCS:
602 	    fcfname = "DCS (command signal)";
603 	    break;
604 	case FCF_CSI:
605 	    fcfname = "CSI (called subscriber id)";
606 	    break;
607 	case FCF_TSI:
608 	    fcfname = "TSI (sender id)";
609 	    break;
610 	case FCF_CFR:
611 	    fcfname = "CFR (confirmation to receive)";
612 	    break;
613 	case FCF_FTT:
614 	    fcfname = "FTT (failure to train)";
615 	    break;
616 	case FCF_CRP:
617 	    fcfname = "CRP (command repeat)";
618 	    break;
619 	case FCF_EOM:
620 	    fcfname = "EOM (more documents)";
621 	    break;
622 	case FCF_MPS:
623 	    fcfname = "MPS (more pages, same document)";
624 	    break;
625 	case FCF_EOR:
626 	    fcfname = "EOR (end of retransmission)";
627 	    break;
628 	case FCF_EOP:
629 	    fcfname = "EOP (no more pages or documents)";
630 	    break;
631 	case FCF_RR:
632 	    fcfname = "RR (receive ready)";
633 	    break;
634 	case FCF_CTC:
635 	    fcfname = "CTC (continue to correct)";
636 	    break;
637 	case FCF_PRI_EOM:
638 	    fcfname = "PRI-EOM (more documents after interrupt)";
639 	    break;
640 	case FCF_PRI_MPS:
641 	    fcfname = "PRI-MPS (more pages after interrupt)";
642 	    break;
643 	case FCF_PRI_EOP:
644 	    fcfname = "PRI-EOP (no more pages after interrupt)";
645 	    break;
646 	case FCF_PPS:
647 	    fcfname = "PPS (partial page signal)";
648 	    break;
649 	case FCF_DCN:
650 	    fcfname = "DCN (disconnect)";
651 	    break;
652 	case FCF_CTR:
653 	    fcfname = "CTR (confirm continue to correct)";
654 	    break;
655 	case FCF_NSF:
656 	    fcfname = "NSF (non-standard facilities)";
657 	    break;
658 	case FCF_NSS:
659 	    fcfname = "NSS (non-standard setup)";
660 	    break;
661 	case FCF_MCF:
662 	    fcfname = "MCF (message confirmation)";
663 	    break;
664 	case FCF_RTN:
665 	    fcfname = "RTN (retrain negative)";
666 	    break;
667 	case FCF_RTP:
668 	    fcfname = "RTP (retrain positive)";
669 	    break;
670 	case FCF_PIN:
671 	    fcfname = "PIN (procedural interrupt negative)";
672 	    break;
673 	case FCF_PIP:
674 	    fcfname = "PIP (procedural interrupt positive)";
675 	    break;
676 	case FCF_RNR:
677 	    fcfname = "RNR (receive not ready)";
678 	    break;
679 	case FCF_ERR:
680 	    fcfname = "ERR (confirm end of retransmisison)";
681 	    break;
682 	case FCF_PPR:
683 	    fcfname = "PPR (partial page request)";
684 	    break;
685 	case FCF_SUB:
686 	    fcfname = "SUB (subaddress)";
687 	    break;
688 	case FCF_PWD:
689 	    fcfname = "PWD (password)";
690 	    break;
691 	default:
692 	    protoTrace("unknown FCF 0x%X", fcf);
693 	    return;
694     }
695     protoTrace("%s %s", dir, (const char*) fcfname);
696 }
697 
698 /*
699  * Modem i/o support.
700  */
701 
702 /*
703  * Miscellaneous server interfaces hooks.
704  */
isFaxModem() const705 bool FaxModem::isFaxModem() const		{ return true; }
706 
getHDLCTracing()707 bool FaxModem::getHDLCTracing()
708     { return (server.getSessionTracing() & FAXTRACE_HDLC) != 0; }
getECMTracing()709 bool FaxModem::getECMTracing()
710     { return (server.getSessionTracing() & FAXTRACE_ECM) != 0; }
711 
712 FaxSendStatus
sendSetupParams(TIFF * tif,Class2Params & params,FaxMachineInfo & info,Status & eresult)713 FaxModem::sendSetupParams(TIFF* tif, Class2Params& params,
714     FaxMachineInfo& info, Status& eresult)
715 {
716     return server.sendSetupParams(tif, params, info, eresult);
717 }
718 
719 
720 /*
721  * Record the file offset to the start of the data
722  * in the file.  We write zero bytes to force the
723  * strip offset to be setup in case this is the first
724  * time the strip is being written.
725  */
726 void
recvStartPage(TIFF * tif)727 FaxModem::recvStartPage(TIFF* tif)
728 {
729     u_char null[1];
730     (void) TIFFWriteRawStrip(tif, 0, null, 0);
731     (void) TIFFGetField(tif, TIFFTAG_STRIPOFFSETS, &savedWriteOff);
732     (void) TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &savedStripByteCounts);
733     pageStarted = true;
734 }
735 
736 /*
737  * Reset the TIFF state for the current page so that
738  * subsequent data overwrites anything previously
739  * written.  This is done by reseting the file offset
740  * and setting the strip's bytecount and offset to
741  * values they had at the start of the page.  This
742  * scheme assumes that only page data is written to
743  * the file between the time recvSetupPage is called
744  * and recvResetPage is called.
745  */
746 void
recvResetPage(TIFF * tif)747 FaxModem::recvResetPage(TIFF* tif)
748 {
749     if (!pageStarted) return;
750     TIFFSetWriteOffset(tif, 0);		// force library to reset state
751     TIFFSetField(tif, TIFFTAG_STRIPOFFSETS, savedWriteOff);
752     TIFFSetField(tif, TIFFTAG_STRIPBYTECOUNTS, savedStripByteCounts);
753 }
754 
755 void
countPage(PageType pt)756 FaxModem::countPage(PageType pt)
757 {
758     pageNumber++;
759     pageNumberOfJob++;
760 
761     if (pt == PAGE_COVER)
762 	 pageNumberCovered++;
763     if (pt == PAGE_SKIP)
764 	pageNumberSkipped++;
765 }
766 
767 int
getPageNumber()768 FaxModem::getPageNumber()
769 {
770     return pageNumber;
771 }
772 
773 void
notifyPageSent(TIFF * tif,PageType pt)774 FaxModem::notifyPageSent(TIFF* tif, PageType pt)
775 {
776     if (curreq)
777 	server.notifyPageSent(*curreq, TIFFFileName(tif), pt);
778 }
779 
780 #include "MemoryDecoder.h"
781 
782 void
correctPhaseCData(u_char * buf,u_long & pBufSize,u_int fillorder,const Class2Params & params,uint32 & rows)783 FaxModem::correctPhaseCData(u_char* buf, u_long& pBufSize,
784                             u_int fillorder, const Class2Params& params, uint32& rows)
785 {
786     u_char* endOfData;
787     MemoryDecoder dec1(buf, params.pageWidth(), pBufSize, fillorder, params.is2D(), false);
788     dec1.fixFirstEOL();
789     /*
790      * We have to construct new decoder. See comments to cutExtraRTC().
791      */
792     MemoryDecoder dec2(buf, params.pageWidth(), pBufSize, fillorder, params.is2D(), false);
793     endOfData = dec2.cutExtraRTC();
794     // we don't update rows because we don't decode the entire image
795     if( endOfData )
796         pBufSize = endOfData - buf;
797 }
798 
799 u_char*
convertPhaseCData(u_char * buf,u_long & totdata,u_int fillorder,const Class2Params & params,const Class2Params & newparams,uint32 & rows)800 FaxModem::convertPhaseCData(u_char* buf, u_long& totdata, u_int fillorder,
801 			    const Class2Params& params, const Class2Params& newparams, uint32& rows)
802 {
803     MemoryDecoder dec(buf, params.pageWidth(), totdata, fillorder, params.is2D(), (params.df == DF_2DMMR));
804     u_char* data = dec.convertDataFormat(newparams);
805     totdata = dec.getCC();
806     rows = dec.getRows();
807     return (data);
808 }
809 
isCountingSkippedPages() const810 bool FaxModem::isCountingSkippedPages () const
811 {
812     return conf.countSkippedPages;
813 }
814 
815 
816