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