HylaFAX The world's most advanced open source fax server |
* Lee Howard <faxguy@xxxxxxxxxxxxxxxx> [060112 11:38]: > Attached is a patch that will give you this feature. It should apply to > most recent versions of HylaFAX. If you desire it in a tarball it is in > 4.2.5.1 which can be found at: > > http://hylafax.sourceforge.net/news/4.2.5.1.php > > The feature basically adds an "owner" option to DestControls. > Documentation can be seen in 'man destctrls' and here: > > http://hylafax.sourceforge.net/man/destctrls.php > > But, basically by adding an "owner" field to the DestControls entry you > will restrict the application of that entry to apply only to jobs > submitted by that owner (hfaxd login username). So, for example > DestControls entries of: > > .* owner=omer modem=ttyS0 > .* owner=lee modem=ttyS1 > > This would make all jobs submitted by "omer" be sent through modem ttyS0 > and all jobs submitted by "lee" be sent through modem ttyS1. I've attached the start of another approach to gaining this functionality, but in a bit more generic. The intention is to make a "jobcontrls", similar to destcontrols. The idea is that you can control jobs (same as destcontrols) based on a match of any (or no) job parameters. This version currently only supports dest, owner, and client, but can easily be extended to include almost any user-specifiable job parameter. Any, or none of the 3 fields can be matched, and all are regex matches. This patch slightly changes the format of the destcontrols file (with the thought that this could grow into a jobcontrol file, or such, possibly with a backwards compatible destcontrols parser ). The file format is: [dest=<dest regex>] [owner=<owner_regex>] [client=<client_regex>] action=... So, basically, instead of just the single "destination regex", you can specify regex for other input fields, somehting like: dest=911 RejectNotice="No 911" owner=aidan client=ifax RejectNotice=reject-aidan-remote owner=aidan client=localhost RejectNotice=reject-aidan-LOCAL dest=+1215 client=localhost Modem=localgroup I have a few concerns with the format of this file. I don't really like the "overloading" of both input fields and output fields with the = sign. A possible format could be a white-space separated file: <dest_regex> <owner_regex> <client_regex> <action1> [ [<action2] ... ] but this doesn't lead to a very extendable format, and makes adding (or removing) fields problematic. Thoughts, comments? a. -- Aidan Van Dyk aidan@xxxxxxxx Senior Software Developer +1 215 438-4638 x8103 iFAX Solutions, Inc. http://www.ifax.com/
===== faxd/DestControl.c++ 1.10 vs edited ===== --- 1.10/faxd/DestControl.c++ 2004-04-21 12:30:45 -04:00 +++ edited/faxd/DestControl.c++ 2006-03-14 14:08:15 -05:00 @@ -42,12 +42,41 @@ #define isDefined(b) (defined & b) #define setDefined(b) (defined |= b) + +static bool IsREmatch (RE* p, const fxStr& m) +{ + if (p) + return p->Find(m); + return true; +} + +static bool IsREerror (RE* p) +{ + if (p) + return p->getErrorCode() > REG_NOMATCH; + return false; +} + const DestControlInfo DestControlInfo::defControlInfo; -DestControlInfo::DestControlInfo() : pattern("") { defined = 0; } -DestControlInfo::DestControlInfo(const char* re) : pattern(re) { defined = 0; } +DestControlInfo::DestControlInfo() +{ + defined = 0; +} + +#ifdef AIDAN +DestControlInfo::DestControlInfo(const char* d, const char* o) + : dest(d) + , owner(o) +{ + defined = 0; +} +#endif + DestControlInfo::DestControlInfo(const DestControlInfo& other) - : pattern(other.pattern) + : dest(other.dest) + , owner(other.owner) + , client(other.client) , rejectNotice(other.rejectNotice) , modem(other.modem) , tod(other.tod) @@ -71,7 +100,15 @@ void DestControlInfo::parseEntry(const char* tag, const char* value, bool quoted) { - if (streq(tag, "rejectnotice")) { + if (streq(tag, "destination")) { + dest = new RE(value); + } else if (streq(tag, "dest")) { + dest = new RE(value); + } else if (streq(tag, "owner")) { + owner = new RE(value); + } else if (streq(tag, "client")) { + client = new RE(value); + } else if (streq(tag, "rejectnotice")) { rejectNotice = value; } else if (streq(tag, "modem")) { modem = value; @@ -100,6 +137,7 @@ vres = getNumber(value); setDefined(DCI_VRES); } else { + logError(" - appending as args"); if( args != "" ) args.append('\0'); const char* quote = quoted ? "\"" : ""; @@ -203,7 +241,7 @@ } const DestControlInfo& -DestControl::operator[](const fxStr& canon) +DestControl::find (const fxStr& f_dest, const fxStr& f_owner, const fxStr& f_client) { struct stat sb; if (Sys::stat(filename, sb) == 0 && sb.st_mtime > lastModTime) { @@ -213,7 +251,9 @@ } for (u_int i = 0, n = info.length(); i < n; i++) { DestControlInfo& dci = info[i]; - if (dci.pattern.Find(canon)) + if (IsREmatch(dci.dest, f_dest) + && IsREmatch(dci.owner, f_owner) + && IsREmatch(dci.client, f_client) ) return (dci); } return (DestControlInfo::defControlInfo); @@ -269,26 +309,8 @@ for (;;) { if (!readLine(fp, line, sizeof (line)-1)) return (false); - char* cp; - for (cp = line; *cp && !isspace(*cp); cp++) - ; - if (*cp == '\0') - continue; - if (cp == line) { - parseError("Missing regular expression."); - skipEntry(fp, line, sizeof (line)-1); - return (true); - } - *cp++ = '\0'; - DestControlInfo dci(line); - if (dci.pattern.getErrorCode() > REG_NOMATCH) { - RE& re = dci.pattern; - fxStr emsg; - re.getError(emsg); - parseError("Bad regular expression: %s: " | emsg, re.pattern()); - skipEntry(fp, line, sizeof (line)-1); - return (true); - } + DestControlInfo dci; + char* cp = line; for (;;) { while (isspace(*cp)) cp++; @@ -343,6 +365,30 @@ *cp++ = '\0'; if (tag[0] != '\0') dci.parseEntry(tag, value, quoted); + } + if (IsREerror(dci.dest) ) { + RE& re = *dci.dest; + fxStr emsg; + re.getError(emsg); + parseError("Bad destination regular expression: %s: " | emsg, re.pattern()); + skipEntry(fp, line, sizeof (line)-1); + return (true); + } + if (IsREerror(dci.owner) ) { + RE& re = *dci.owner; + fxStr emsg; + re.getError(emsg); + parseError("Bad owner regular expression: %s: " | emsg, re.pattern()); + skipEntry(fp, line, sizeof (line)-1); + return (true); + } + if (IsREerror(dci.client) ) { + RE& re = *dci.client; + fxStr emsg; + re.getError(emsg); + parseError("Bad client regular expression: %s: " | emsg, re.pattern()); + skipEntry(fp, line, sizeof (line)-1); + return (true); } } } ===== faxd/DestControl.h 1.7 vs edited ===== --- 1.7/faxd/DestControl.h 2004-04-21 12:30:45 -04:00 +++ edited/faxd/DestControl.h 2006-03-14 14:08:34 -05:00 @@ -40,7 +40,12 @@ */ class DestControlInfo { private: - RE pattern; // destination pattern + /* Match fields */ + REPtr dest; // destination pattern + REPtr owner; // owner pattern + REPtr client; // client pattern + + /* Control fields */ u_long defined; // parameters that were defined u_int maxConcurrentCalls; // max number of parallel calls u_int maxSendPages; // max pages in a send job @@ -58,11 +63,14 @@ friend class DestControl; public: - DestControlInfo(const char* regex); +#ifdef AIDAN + DestControlInfo(const char* dest = "", const char* owner = ""); +#endif DestControlInfo(); DestControlInfo(const DestControlInfo& other); ~DestControlInfo(); + int compare(const DestControlInfo*) const; void parseEntry(const char* tag, const char* value, bool quoted); @@ -102,6 +110,7 @@ void setFilename(const char* filename); - const DestControlInfo& operator[](const fxStr&); +// const DestControlInfo& operator[](const fxStr&); + const DestControlInfo& find (const fxStr& canon, const fxStr& owner, const fxStr& client); }; #endif /* _DestControl_ */ ===== faxd/faxQueueApp.c++ 1.70 vs edited ===== --- 1.70/faxd/faxQueueApp.c++ 2005-10-27 17:53:07 -04:00 +++ edited/faxd/faxQueueApp.c++ 2006-03-14 14:09:02 -05:00 @@ -232,6 +232,11 @@ closedir(dir); } +const DestControlInfo& +faxQueueApp::getDCI(const Job& j, const FaxRequest*r) +{ + return destCtrls.find(j.dest, r->owner, r->client); +} /* * Process a job. Prepare it for transmission and * pass it on to the thread that does the actual @@ -442,8 +447,8 @@ setDead(job); } } - if (processnext) processJob(*targetjob, targetjob->breq, destJobs[targetjob->dest], destCtrls[targetjob->dest]); - else if (startsendjob) sendJobStart(*targetjob->bfirst(), targetjob->bfirst()->breq, destCtrls[targetjob->dest]); + if (processnext) processJob(*targetjob, targetjob->breq, destJobs[targetjob->dest], getDCI(*targetjob, targetjob->breq)); + else if (startsendjob) sendJobStart(*targetjob->bfirst(), targetjob->bfirst()->breq, getDCI(*targetjob, targetjob->breq)); else { /* * This destination was marked as called, but all jobs to this @@ -2188,17 +2193,20 @@ * ready for processing. */ Job* jb; - const DestControlInfo& dci = destCtrls[job.dest]; u_int n = 1; - while (isOKToCall(di, dci, n) && (jb = di.nextBlocked())) { - setReadyToRun(*jb); - if (!di.supportsBatching()) n++; + while (jb = di.nextBlocked()) { FaxRequest* req = readRequest(*jb); - if (req) { + if (! req) + continue; + const DestControlInfo& dci = getDCI(job, req); + if (isOKToCall(di, dci, n) ) + { + setReadyToRun(*jb); + if (!di.supportsBatching()) n++; req->notice = ""; updateRequest(*req, *jb); - delete req; } + delete req; } } @@ -2291,7 +2299,7 @@ * Do per-destination processing and checking. */ DestInfo& di = destJobs[job.dest]; - const DestControlInfo& dci = destCtrls[job.dest]; + const DestControlInfo& dci = getDCI(job, req); /* * Constrain the maximum number of times the phone * will be dialed and/or the number of attempts that ===== faxd/faxQueueApp.h 1.20 vs edited ===== --- 1.20/faxd/faxQueueApp.h 2005-09-27 15:03:09 -04:00 +++ edited/faxd/faxQueueApp.h 2006-03-14 14:06:30 -05:00 @@ -174,6 +174,7 @@ void startTimeout(long ms); void stopTimeout(const char* whichdir); const fxStr& pickCmd(const FaxRequest& req); + const DestControlInfo& getDCI(const Job& job, const FaxRequest* req); // FIFO-related stuff void childStatus(pid_t, int); // Dispatcher hook int inputReady(int); // Dispatcher hook
Attachment:
signature.asc
Description: Digital signature