📄 adfaxsrv.pas
字号:
(***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TurboPower Async Professional
*
* The Initial Developer of the Original Code is
* TurboPower Software
*
* Portions created by the Initial Developer are Copyright (C) 1991-2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** *)
{*********************************************************}
{* ADFAXSRV.PAS 4.06 *}
{*********************************************************}
{
Description:
Implements the fax server components. The idea of the
fax server components is to create fax job files (APJ)
which consist of a job header (TApdFaxJobHeader),
1 or more recipient headers (TApdFaxRecipientHeader),
a text cover page, and a fax file (APF). The APJ is
manipulated with the TApdFaxJobHandler class.
-The TApdFaxClient component wraps the handler class.
-The TApdFaxServerManager component monitors a dir
when a server asks for a job to send. The manager
does this by opening each APJ and checking the job
header & finds the job with the earliest scheduled
date.
-The TApdFaxServer wraps a TApdSendFax, TApdReceiveFax
and a few supporting components. The Server is the
only part that talks to the modem. The server
requests jobs based on the SendQueryInterval
property. The server can also receive faxes.
Known problems:
These components were designed to be compatible with D1 Standard/Win16,
so we couldn't use any built-in DB support or other cool features.
Expansion points:
-Convert over to require TAPI, and the TAPI passive
answering with the internal TApdReceiveFax. A lot
of code is now dedicated to switching back and
forth between send/recv.
-Change the manager so it is data-aware (looks in
a DB instead of a dir)
}
{Global defines potentially affecting this unit}
{$I AWDEFINE.INC}
{Options required for this unit}
{$G+,X+,F-,V-,P-,T-,B-}
unit AdFaxSrv;
{ -Integrated Fax Server }
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, OoMisc, AdFax, AdPort, AdTapi, AdFaxPrn, AdExcept, AdFStat,
AdFIDlg {used for TShowJobInfoDialog};
const
adfDefDelayBetweenSends = 18; {in ticks}
adfDefSendQueryInterval = 30; {in miliseconds (30 seconds) }
adfDefJobFileExt = 'APJ';
apfDefJobHeaderID = 810176577; {'APJ0' in hex editor}
adfDefFaxServerManagerPaused = False;
ServerManagerLockFileName = 'SRVMGR.LCK';
{ Status byte for Job Header / Recipient Info }
stNone = 0; { no faxes sent / fax job not sent }
stPartial = 1; { some faxes sent / fax job being sent }
stComplete = 2; { no more faxes to send / fax job sent }
stPaused = 3; { entire file paused / this job is paused }
type
TFaxServerMode = (fsmIdle, fsmSend, fsmReceive);
{ predefine the classes }
TApdFaxServerManager = class;
TApdCustomFaxServer = class;
{ event types }
TFaxServerStatusEvent = procedure(CP : TObject; FaxMode: TFaxServerMode;
First, Last : Boolean; Status: Word) of object;
TFaxServerFatalErrorEvent = procedure(CP: TObject; FaxMode: TFaxServerMode;
ErrorCode, HangupCode: Integer) of object;
TFaxServerFinishEvent = procedure(CP: TObject; FaxMode: TFaxServerMode;
ErrorCode: Integer) of object;
TFaxServerPortOpenCloseEvent = procedure(CP: TObject; Opening: Boolean) of object;
TFaxServerAcceptEvent = procedure(CP : TObject; var Accept : Boolean) of object;
TFaxServerNameEvent = procedure(CP : TObject; var Name : TPassString) of object;
TFaxServerLogEvent = procedure(CP : TObject; LogCode : TFaxLogCode;
ServerCode : TFaxServerLogCode) of object;
{ TApdFaxServerManager events }
TFaxServerManagerQueriedEvent = procedure(Mgr : TApdFaxServerManager;
QueryFrom : TApdCustomFaxServer; const JobToSend : string) of object;
TManagerUpdateRecipientEvent = procedure (Mgr : TApdFaxServerManager;
JobFile : string; JobHeader : TFaxJobHeaderRec;
var RecipHeader : TFaxRecipientRec) of object;
TManagerUserGetJobEvent = procedure(Mgr : TApdFaxServerManager;
QueryFrom : TApdCustomFaxServer; var JobFile, FaxFile,
CoverFile : string; var RecipientNum : Integer) of object;
{ Object used for ApdFaxServerManager.FFaxList to keep track of job files
only used in ApdFaxServerManager's GetNextFax and UpdateStatus methods}
TFaxListObj = class(TObject)
FileTime: Integer;
JobHeader: TFaxJobHeaderRec;
end;
{ - The TApdFaxJobHandler class contains methods to manipulate APJ files, }
{ the TApdFaxServerManager, and TApdFaxClient components are derived }
{ from this class to provide uniform APJ handling }
TApdFaxJobHandler = class(TApdBaseComponent)
public
{ - Adds a TFaxRecipientRec for a new recipient }
procedure AddRecipient(JobFileName: TPassString;
RecipientInfo: TFaxRecipientRec);
{ - Makes an APJ file from an APF, requires a recipient }
procedure MakeJob(FaxName, CoverName, JobName, Sender, DestName: TPassString;
Recipient: TFaxRecipientRec);
{ show dialog displaying information about the APJ }
function ShowFaxJobInfoDialog(JobFileName, DlgCaption: TPassString): TModalResult;
{ - Extracts APF file from APJ, and saves to FaxName }
procedure ExtractAPF(JobFileName, FaxName: TPassString);
{ - Extracts CoverPage text from APJ, and saves to CoverName, returns }
{ true if a cover file is available, false otherwise }
function ExtractCoverFile(JobFileName, CoverName: TPassString): Boolean;
{ - returns the FaxJobInfoRec for the Count recipient in the Job file }
function GetRecipient(JobFileName: TPassString; Index: Integer;
var Recipient: TFaxRecipientRec): Integer;
{ - returns the FaxJobHeaderRec for the specified JobFile }
procedure GetJobHeader(JobFileName: TPassString;
var JobHeader: TFaxJobHeaderRec);
{- returns the status byte for the specified recipient }
function GetRecipientStatus(JobFileName: TPassString;
JobNum : Integer) : Integer;
{ - cancels an individual recipient }
procedure CancelRecipient(JobFileName: TPassString; JobNum : Byte);
{ - Concatenates 2 APF files into 1 }
procedure ConcatFaxes(DestFaxFile: TPassString; FaxFiles: array of TPassString);
{- Resets all stPartial status flags to stNone, can set AttemptNum to 0 }
procedure ResetAPJPartials(JobFileName: TPassString; {!!.03}
ResetAttemptNum : Boolean); {!!.03}
{- Resets all status flags in an APJ to stNone}
procedure ResetAPJStatus(JobFileName: TPassString);
{- Resets individual recipient with new status, updates job header }
procedure ResetRecipientStatus(JobFileName: TPassString;
JobNum, NewStatus: Byte);
{- Reschedules a recipient, updates job header }
procedure RescheduleJob(JobFileName : TPassString;
JobNum : Integer; NewSchedDT : TDateTime; ResetStatus: Boolean);
end;
{ - the ApdFaxServerManager controls the flow of fax jobs to the ApdFaxServer.
An ApdFaxClient will deposit pre-composed fax job files (APJ) into the
MonitorDir folder, and an ApdFaxServer will call the GetNextFax method to
get the next fax to be sent }
TApdFaxServerManager = class(TApdFaxJobHandler)
private
FMonitorDir: TPassString;
FFaxList: TStringList;
FJobFileExt: TPassString;
FPaused: Boolean;
FLockFile: TFileStream;
FDeleteOnComplete: Boolean;
FFirstGetJob : Boolean;
FInGetJob : Boolean;
FFaxServerManagerQueriedEvent: TFaxServerManagerQueriedEvent;
FManagerUpdateRecipientEvent: TManagerUpdateRecipientEvent;
FManagerUserGetJobEvent: TManagerUserGetJobEvent;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
{ - returns the file name of the next fax job to send }
function GetNextFax: TPassString;
{ - returns the scheduled send time of the specified fax job }
function GetSchedTime(JobFileName: TPassString): TDateTime;
{ - Returns the fax job in Recipient, True if ready, False otherwise }
function GetJob(var Recipient: TFaxRecipientRec;
QueryFrom: TApdCustomFaxServer; var JobFileName, FaxFile,
CoverFile: TPassString): Boolean;
{ - updates status of individual fax jobs }
procedure UpdateStatus(JobFileName: TPassString; JobNumber, Result: Word;
Failed: Boolean);
{ - Resets internal fax list and properties }
procedure Reset;
procedure SetMonitorDir(const Value: TPassString);
property FaxList : TStringList
read FFaxList;
published
{- Delete the APJ after all jobs are complete }
property DeleteOnComplete: Boolean
read FDeleteOnComplete write FDeleteOnComplete;
{ - The directory where we will look for APJ files }
property MonitorDir: TPassString
read FMonitorDir write SetMonitorDir;
{ - The default extension for APJ Files }
property JobFileExt: TPassString
read FJobFileExt write FJobFileExt;
{ - Pauses all fax jobs }
property Paused: Boolean
read FPaused write FPaused default adfDefFaxServerManagerPaused;
{ - Event generated when GetJob is called }
property OnQueried : TFaxServerManagerQueriedEvent
read FFaxServerManagerQueriedEvent
write FFaxServerManagerQueriedEvent;
{ - Event generated when a recipient is complete (ecOK or failed ) }
property OnRecipientComplete : TManagerUpdateRecipientEvent
read FManagerUpdateRecipientEvent
write FManagerUpdateRecipientEvent;
{ - Event generated to provide custom scheduling from app }
{ If this event is defined, this event will be responsible for }
{ feeding the fax jobs, the scheduling and queuing built into }
{ the ApdFaxServerManager will not be used }
property OnCustomGetJob : TManagerUserGetJobEvent
read FManagerUserGetJobEvent
write FManagerUserGetJobEvent;
end;
{ - The ApdFaxClient composes APJ files for use by the ApdFaxServerManager. }
TApdFaxClient = class(TApdFaxJobHandler)
private
FJobName: TPassString;
FSender: TPassString;
FCoverFileName: TPassString;
FJobFileName: TPassString;
FFaxFileName: TPassString;
function GetScheduleDateTime: TDateTime;
procedure SetHeaderLine(const Value: TPassString);
procedure SetHeaderRecipient(const Value: TPassString);
procedure SetHeaderTitle(const Value: TPassString);
procedure SetPhoneNumber(const Value: TPassString);
procedure SetScheduleDateTime(const Value: TDateTime);
function GetHeaderLine: TPassString;
function GetHeaderRecipient: TPassString;
function GetHeaderTitle: TPassString;
function GetPhoneNumber: TPassString;
public
{ - contains info about this job}
Recipient: TFaxRecipientRec;
constructor Create(AOwner: TComponent); override;
{ - Generic copying method }
function CopyJobToServer(SourceJob, DestJob: TPassString;
OverWrite: Boolean): Integer;
{ - Calls MakeJob with our property values }
procedure MakeFaxJob;
{ - accepts TDateTime input to schedule job }
property ScheduleDateTime: TDateTime
read GetScheduleDateTime write SetScheduleDateTime;
published
{ properties related to job header }
property CoverFileName: TPassString
read FCoverFileName write FCoverFileName;
property FaxFileName: TPassString
read FFaxFileName write FFaxFileName;
property JobFileName: TPassString
read FJobFileName write FJobFileName;
property JobName: TPassString
read FJobName write FJobName;
property Sender: TPassString
read FSender write FSender;
{ properties related to recipient, access methods refer to Recipient fields }
property PhoneNumber: TPassString
read GetPhoneNumber write SetPhoneNumber;
property HeaderLine: TPassString
read GetHeaderLine write SetHeaderLine;
property HeaderRecipient: TPassString
read GetHeaderRecipient write SetHeaderRecipient;
property HeaderTitle: TPassString
read GetHeaderTitle write SetHeaderTitle;
end;
TApdCustomFaxServer = class(TApdCustomAbstractFax)
private
{ points to other components on the form }
FComPort: TApdCustomComPort;
FTapiDevice: TApdCustomTapiDevice;
FStatusDisplay: TApdAbstractFaxStatus;
FFaxLog: TApdFaxLog;
{ internal components }
FSendFax: TApdSendFax;
FRecvFax: TApdReceiveFax;
FSendQueryTimer: TTimer;
FSoftwareFlow: Boolean;
FSafeMode: Boolean;
FExitOnError: Boolean;
FBlindDial: Boolean;
FToneDial: Boolean;
FConstantStatus: Boolean;
FInitBaud: Integer;
FNormalBaud: Integer;
FCoverFile: TPassString;
FHeaderTitle: TPassString;
FPhoneNumber: TPassString;
FHeaderLine: TPassString;
FHeaderRecipient: TPassString;
FDestinationDir: TPassString;
FFaxFile: TPassString;
FFaxFileExt: TPassString;
FHeaderSender: TPassString;
FFaxClass: TFaxClass;
FFaxNameMode: TFaxNameMode;
FModemInit: TModemString;
FStationID: TStationID;
FAnswerOnRing: Word;
FBufferMinimum: Word;
FStatusInterval: Word;
FMaxSendCount: Word;
FMonitoring: Boolean;
FOldMonitoring: Boolean;
FFaxPrinter: TApdCustomFaxPrinter;
FPrintOnReceive: Boolean;
FFaxServerMode: TFaxServerMode;
FFaxInProgress: Boolean;
FDesiredBPS: Word;
FDesiredECM: Boolean;
FDetectBusy: Boolean;
FPageLength: LongInt;
FDelayBetweenSends: Word;
FServerManager: TApdFaxServerManager;
FSendQueryInterval: Integer;
FDialAttempts: Word;
FDialWait: Word;
FDialRetryWait: Word;
FDialPrefix: TModemString;
FEnhFont: TFont;
FEnhHeaderFont: TFont;
FEnhTextEnabled: Boolean;
WaitingOnTapi: Boolean;
FServerLogCode: TFaxServerLogCode;
FFaxServerFatalErrorEvent: TFaxServerFatalErrorEvent;
FFaxServerStatusEvent: TFaxServerStatusEvent;
FFaxServerFinishEvent: TFaxServerFinishEvent;
FFaxServerPortOpenCloseEvent: TFaxServerPortOpenCloseEvent;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -