⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jobs.c++

📁 fax相关的东西
💻 C++
📖 第 1 页 / 共 4 页
字号:
/*	$Id: Jobs.c++,v 1.29 2006/06/12 18:28:55 aidan Exp $ *//* * Copyright (c) 1995-1996 Sam Leffler * Copyright (c) 1995-1996 Silicon Graphics, Inc. * HylaFAX is a trademark of Silicon Graphics * * Permission to use, copy, modify, distribute, and sell this software and  * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. *  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.   *  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE  * OF THIS SOFTWARE. */#include "port.h"#include "config.h"#include "Sys.h"#include "HylaFAXServer.h"#include "Dispatcher.h"#include "class2.h"#include <sys/file.h>#include <ctype.h>/* * Job state query and control commands. */Job::Job(const fxStr& qf, int f) : FaxRequest(qf,f){    lastmod = 0;    queued = false;}Job::~Job() {}/* * We need to override the default logic because faxq * assumes it's working directory is at the top of the * spooling area and we may be elsewhere.  We can also * simplify things because we know we're chroot'd to * the top of the spooling area--thus we don't need to * check for ``..'' and ``/'' being used to reference * files outside the spooling area. */boolJob::checkDocument(const char* pathname){    struct stat sb;    if (FileCache::lookup(fxStr::format("/%s", pathname), sb))	return (true);    int fd = Sys::open(pathname, 0);    if (fd == -1) {	logError("Can not access document file \"%s\": %s",	    pathname, strerror(errno));	return (false);    }    Sys::close(fd);    logError("Undetermined error with document file \"%s\"", pathname);    return (false);}fxIMPLEMENT_StrKeyPtrValueDictionary(JobDict, Job*)/* * Job state parameter access controls. * * There are three levels of access control applied to job state * information: administrator, owner, and other. * Access is controlled on a read+write basis.  Write accesses * can be further restricted to constrain written values to * be within a range; this is used to allow users to change * parameters within a restricted range (e.g. to up the maximum * number of tries but still constrain it to a sane value). */#define	A_RUSR	0400	// read permission: owner#define	A_WUSR	0200	// abitrary write permission: owner#define	A_MUSR	0100	// restricted write permission: owner#define	A_RADM	0040	// read permission: administrator#define	A_WADM	0020	// abitrary write permission: administrator#define	A_MADM	0010	// restricted write permission: administrator#define	A_ROTH	0004	// read permission: other#define	A_WOTH	0002	// abitrary write permission: other#define	A_MOTH	0001	// restricted write permission: other#define	A_READ	 004#define	A_WRITE	 002#define	A_MODIFY 001#define	N(a)		(sizeof (a) / sizeof (a[0]))static const struct {    Token	t;    u_int	protect;		// read+write protection} params[] = {    { T_BEGBR,		A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_BEGST,		A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_CHOPTHRESH,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_CLIENT,		A_RUSR|A_RADM|A_WADM|A_ROTH },    { T_COMMID,		A_RUSR|A_RADM|A_ROTH },    { T_COMMENTS,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_COVER,		A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_DATAFORMAT,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_DIALSTRING,	A_RUSR|A_WUSR|A_RADM|A_WADM },    { T_DOCUMENT,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_DONEOP,		A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_EXTERNAL,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_FAXNUMBER,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_FROM_COMPANY,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_FROM_LOCATION,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_FROM_USER,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_FROM_VOICE,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_GROUPID,	A_RUSR|A_RADM|A_ROTH },    { T_JOBID,		A_RUSR|A_RADM|A_ROTH },    { T_JOBINFO,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_JOBTYPE,	A_RUSR|A_RADM|A_ROTH },    { T_LASTTIME,	A_RUSR|A_MUSR|A_RADM|A_WADM|A_ROTH },    { T_MAXDIALS,	A_RUSR|A_MUSR|A_RADM|A_WADM|A_ROTH },    { T_MAXPAGES,	A_RUSR|A_MUSR|A_RADM|A_WADM|A_ROTH },    { T_MAXTRIES,	A_RUSR|A_MUSR|A_RADM|A_WADM|A_ROTH },    { T_MINBR,		A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_MODEM,		A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_OWNER,		A_RUSR|A_RADM|A_WADM|A_ROTH },    { T_NDIALS,		A_RUSR|A_RADM|A_ROTH },    { T_NOTIFY,		A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_NOTIFYADDR,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_NPAGES,		A_RUSR|A_RADM|A_ROTH },    { T_NTRIES,		A_RUSR|A_RADM|A_ROTH },    { T_PAGECHOP,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_PAGELENGTH,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_PAGEWIDTH,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_PASSWD,		A_RUSR|A_WUSR|A_RADM|A_WADM },    { T_POLL,		A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_REGARDING,	A_RUSR|A_MUSR|A_RADM|A_WADM|A_ROTH },    { T_RETRYTIME,	A_RUSR|A_MUSR|A_RADM|A_WADM|A_ROTH },    { T_SCHEDPRI,	A_RUSR|A_MUSR|A_RADM|A_WADM|A_ROTH },    { T_SENDTIME,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_STATE,		A_RUSR|A_RADM|A_ROTH },    { T_STATUS,		A_RUSR|A_RADM|A_WADM|A_ROTH },    { T_SUBADDR,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_TAGLINE,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_TOTDIALS,	A_RUSR|A_RADM|A_ROTH },    { T_TOTPAGES,	A_RUSR|A_RADM|A_ROTH },    { T_TOTTRIES,	A_RUSR|A_RADM|A_ROTH },    { T_TO_COMPANY,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_TO_LOCATION,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_TO_USER,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_TO_VOICE,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_TSI,		A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_USE_CONTCOVER,	A_RUSR|A_RADM|A_WADM|A_ROTH },    { T_USE_ECM,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_USE_TAGLINE,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_USE_XVRES,	A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_USRKEY,		A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_VRES,		A_RUSR|A_WUSR|A_RADM|A_WADM|A_ROTH },    { T_NIL,		0 },};/* * Check client permission to do the specified operation * on the specified job state parameter.  Operation can * be a combination of A_READ+A_WRITE+A_MODIFY.  Note that * ownership is based on login account and not fax uid; * this may need to be rethought. */boolHylaFAXServer::checkAccess(const Job& job, Token t, u_int op){    u_int m = 0;    if (t == T_JOB) {    	m = jobProtection;    } else {	u_int n = N(params)-1;	u_int i = 0;	while (i < n && params[i].t != t)	    i++;	m = params[i].protect;    }    if (m&op)					// other/public access	return (true);    if (IS(PRIVILEGED) && ((m>>3)&op))		// administrative access	return (true);    if (job.owner == the_user && ((m>>6)&op))	// owner access	return (true);#if 0    if (checkOwnerUid && ((m>>6)&op)) 			// owner UID access	return (true);#endif    return (false);}static struct {    Token	t;    fxStr	Job::* p;} strvals[] = {    { T_JOBTYPE,	&Job::jobtype },    { T_EXTERNAL,	&Job::external },    { T_DIALSTRING,	&Job::number },    { T_NOTIFYADDR,	&Job::mailaddr },    { T_USRKEY,		&Job::jobtag },    { T_MODEM,		&Job::modem },    { T_TO_USER,	&Job::receiver },    { T_TO_COMPANY,	&Job::company },    { T_TO_LOCATION,	&Job::location },    { T_TO_VOICE,	&Job::voice },    { T_FROM_USER,	&Job::sender },    { T_FROM_COMPANY,	&Job::fromcompany },    { T_FROM_LOCATION,	&Job::fromlocation },    { T_FROM_VOICE,	&Job::fromvoice },    { T_PASSWD,		&Job::passwd },    { T_CLIENT,		&Job::client },    { T_FAXNUMBER,	&Job::faxnumber },    { T_TSI,		&Job::tsi },    { T_TAGLINE,	&Job::tagline },    { T_SUBADDR,	&Job::subaddr },    { T_GROUPID,	&Job::groupid },    { T_JOBID,		&Job::jobid },    { T_JOBINFO,	&Job::jobtag },    { T_OWNER,		&Job::owner },    { T_STATUS,		&Job::notice },    { T_DONEOP,		&Job::doneop },    { T_COMMID,		&Job::commid },    { T_REGARDING,	&Job::regarding },    { T_COMMENTS,	&Job::comments },};static struct {    Token	t;    u_short	Job::* p;} shortvals[] = {    { T_TOTPAGES,	&Job::totpages },    { T_NPAGES,		&Job::npages },    { T_NTRIES,		&Job::ntries },    { T_NDIALS,		&Job::ndials },    { T_TOTDIALS,	&Job::totdials },    { T_MAXDIALS,	&Job::maxdials },    { T_TOTTRIES,	&Job::tottries },    { T_MAXTRIES,	&Job::maxtries },    { T_PAGEWIDTH,	&Job::pagewidth },    { T_PAGELENGTH,	&Job::pagelength },    { T_VRES,		&Job::resolution },    { T_SCHEDPRI,	&Job::usrpri },    { T_MINBR,		&Job::minbr },    { T_BEGBR,		&Job::desiredbr },    { T_BEGST,		&Job::desiredst },};static const char* notifyVals[4] = {    "NONE",		// no_notice    "DONE",		// when_done    "REQUEUE",		// when_requeued    "DONE+REQUEUE"	// when_done|when_requeued};static const char* chopVals[4] = {    "DEFAULT",		// chop_default    "NONE",		// chop_none    "ALL",		// chop_all    "LAST"		// chop_last};static const char* dataVals[] = {    "G31D",		// Group 3, 1-D    "G32D",		// Group 3, 2-D    "G32DUNC",		// Group 3, 2-D (w/ uncompressed)    "G4"		// Group 4};static const char* stateVals[] = {    "UNDEFINED",	// undefined state (should never be used)    "SUSPENDED",	// not being scheduled    "PENDING",		// waiting for time to send    "SLEEPING",		// waiting for scheduled timeout    "BLOCKED",		// blocked by concurrent activity    "READY",		// ready to be go, waiting for resources    "ACTIVE",		// actively being processed    "DONE",		// processing completed with success    "FAILED",		// processing completed with failure};static const char* docTypeNames[] = {    "FAX",		// send_fax    "TIFF",		// send_tiff    "TIFF",		// send_tiff_saved    "PDF",		// send_pdf    "PDF",		// send_pdf_saved    "PS",		// send_postscript    "PS",		// send_postscript_saved    "PCL",		// send_pcl    "PCL",		// send_pcl_saved    "DATA",		// send_data    "DATA",		// send_data_saved    "POLL",		// send_poll    "PAGE",		// send_page    "PAGE",		// send_page_saved    "UUCP",		// send_uucp    "UNKNOWN",		// send_unknown};static const char*boolString(bool b){    return (b ? "YES" : "NO");}voidHylaFAXServer::replyBoolean(int code, bool b){    reply(code, "%s", boolString(b));}/* * Check that the job's in-memory state is consistent * with what is on disk.  If the on-disk state is newer then * read it in.  If the job has been removed then remove our * reference, reset the current job back to the default job, * and send the client an error reply.  This method is used * before each place a job's state is access. */boolHylaFAXServer::checkJobState(Job* job){    /*     * Verify job is still around (another process has     * not deleted it) and if the on-disk state has     * been updated, re-read the job description file.     */    struct stat sb;    if (!FileCache::update("/" | job->qfile, sb)) {	jobs.remove(job->jobid);	if (job == curJob)			// make default job current	    curJob = &defJob;	delete job, job = NULL;	return (false);    }    if (job->lastmod < sb.st_mtime) {	(void) updateJobFromDisk(*job);	job->lastmod = sb.st_mtime;    }    return (true);}/* * Check if it's ok to do the specified operation on the * current job's state parameter.  If not, return the appropriate * error reply.   We disallow modifications on jobs that * do not appear to be suspended since otherwise the mods * could be lost (in our case they will be lost due to the * way that things work). */boolHylaFAXServer::checkParm(Job& job, Token t, u_int op){    if (!checkJobState(&job)) {			// insure consistent state	reply(500, "Cannot access job state; job deleted by another party.");	return (false);    } else if (!checkAccess(job, t, op)) {	reply(503, "Permission denied: no %s access to job parameter %s."	    , (op == A_READ ? "read" : "write")	    , parmToken(t)	);	return (false);    } else if ((op & (A_WRITE|A_MODIFY)) &&      job.state != FaxRequest::state_suspended && job.jobid != "default") {	reply(503, "Suspend the job with JSUSP first.");	return (false);    } else	return (true);}/* * Respond to a job state parameter query. */voidHylaFAXServer::replyJobParamValue(Job& job, int code, Token t){    if (!checkParm(job, t, A_READ))	return;    u_int i, n;    switch (t) {    case T_SENDTIME:	if (job.tts != 0) {	    const struct tm* tm = cvtTime(job.tts);	    // XXX should this include seconds?	    reply(code, "%4d%02d%02d%02d%02d%02d"		, tm->tm_year+1900		, tm->tm_mon+1		, tm->tm_mday		, tm->tm_hour		, tm->tm_min		, tm->tm_sec	    );	} else	    reply(code, "NOW");	return;    case T_LASTTIME:	time_t tv; tv = job.killtime - job.tts;		// XXX for __GNUC__	reply(code, "%02d%02d%02d", tv/(24*60*60), (tv/(60*60))%24, (tv/60)%60);	return;    case T_RETRYTIME:	reply(code, "%02d%02d", job.retrytime/60, job.retrytime%60);	return;    case T_STATE:	reply(code, "%s", stateVals[job.state]);	return;    case T_NOTIFY:	reply(code, "%s", notifyVals[job.notify]);	return;    case T_PAGECHOP:	reply(code, "%s", chopVals[job.pagechop]);	return;    case T_CHOPTHRESH:	reply(code, "%g", job.chopthreshold);	return;    case T_DATAFORMAT:	reply(code, "%s", dataVals[job.desireddf]);	return;    case T_USE_ECM:	replyBoolean(code, job.desiredec);	return;    case T_USE_TAGLINE:	replyBoolean(code, job.desiredtl);	return;    case T_USE_XVRES:	replyBoolean(code, job.usexvres);	return;    case T_USE_CONTCOVER:	replyBoolean(code, job.useccover);	return;    case T_DOCUMENT:	for (i = 0, n = job.items.length(); i < n; i++) {	    const FaxItem& fitem = job.items[i];	    // XXX should cover page docs not be shown?	    switch (fitem.op) {	    case FaxRequest::send_pdf:	    case FaxRequest::send_pdf_saved:	    case FaxRequest::send_tiff:	    case FaxRequest::send_tiff_saved:	    case FaxRequest::send_postscript:	    case FaxRequest::send_postscript_saved:	    case FaxRequest::send_pcl:	    case FaxRequest::send_pcl_saved:		lreply(code, "%s %s",		    docTypeNames[fitem.op], (const char*) fitem.item);		break;	    }	}	reply(code, "End of documents.");	return;    case T_COVER:	for (i = 0, n = job.items.length(); i < n; i++) {	    const FaxItem& fitem = job.items[i];	    if (fitem.item.length() > 7 && fitem.item.tail(6) == ".cover") {		switch (fitem.op) {		case FaxRequest::send_tiff:		case FaxRequest::send_tiff_saved:		case FaxRequest::send_pdf:		case FaxRequest::send_pdf_saved:		case FaxRequest::send_postscript:		case FaxRequest::send_postscript_saved:		case FaxRequest::send_pcl:		case FaxRequest::send_pcl_saved:		    reply(code, "%s %s",			docTypeNames[fitem.op], (const char*) fitem.item);		    return;		}	    }	}	reply(code+1, "No cover page document.");	return;    case T_POLL:	for (i = 0, n = job.items.length(); i < n; i++) {	    const FaxItem& fitem = job.items[i];	    if (fitem.op == FaxRequest::send_poll)		lreply(code, "\"%s\" \"%s\"",		    (const char*) fitem.item, (const char*) fitem.addr);	}	reply(code, "End of polling items.");	return;    }    for (i = 0, n = N(strvals); i < n; i++)	if (strvals[i].t == t) {	    reply(code, "%s", (const char*) (job.*strvals[i].p));	    return;	}    for (i = 0, n = N(shortvals); i < n; i++)	if (shortvals[i].t == t) {	    reply(code, "%u", job.*shortvals[i].p);	    return;	}    reply(500, "Botch: no support for querying parameter value.");}void

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -