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

📄 snppserver.c++

📁 fax相关的东西
💻 C++
📖 第 1 页 / 共 3 页
字号:
		reply(500, "%s: Command not implemented.", p->name);	    else if (isShutdown(!IS(LOGGEDIN))) {		reply(421, "Server shutting down.  Goodbye.");		dologout(0);		// XXX	    /*	     * If command requires client to be logged in check	     * for this.  Note that some commands have variants	     * that do not require the client be logged in--these	     * cannot check here and must do it specially below.	     */	    } else if (p->checklogin && !checklogin(p->token))		;	    /*	     * Command is valid, implemented, and the server	     * is available to service it.  If the syntax is	     * correct then reset the number of consecutive	     * bad commands.  Note that since part of the syntax	     * checking is login validation this logic will also	     * catch people typing syntacitcally valid but	     * unacceptable commands just to remain connected.	     */	    else if (cmd(p->token)) {		consecutiveBadCmds = 0;		continue;	    }	}	/*	 * If too many consecutive bad commands have been	 * received disconnect.  This is to safeguard against	 * a client that spews trash down the control connection.	 */	if (++consecutiveBadCmds >= maxConsecutiveBadCmds) {	    /*	     * Check for shutdown so that any shutdown message	     * will get prepended to client reply.	     */	    (void) isShutdown(!IS(LOGGEDIN));	    reply(421, "Too many errors, server shutting down.  Goodbye.");	    dologout(0);	}    }    Dispatcher::instance().startTimer(idleTimeout, 0, this);    return (0);}/* * Protocol command (one line). */boolSNPPServer::cmd(Token t){    fxStr s;    long n;    time_t tv;    switch (t) {    case T_ABOR:			// abort active command (e.g. SEND)	if (CRLF()) {	    logcmd(t);	    ack(250, cmdToken(t));	    return (true);	}	break;    case T_DATA:			// submit multi-line message data	if (CRLF()) {	    logcmd(t);	    dataCmd();	    return (true);	}	break;    case T_HELP:			// return help	if (opt_CRLF()) {	    logcmd(t);	    helpCmd(cmdtab, (char*) NULL);	    return (true);	} else if (string_param(s, "command name")) {	    logcmd(t, "%s", (const char*) s);	    s.raisecase();	    if (s == "SITE")		helpCmd(sitetab, NULL);	    else		helpCmd(cmdtab, s);	    return (true);	}	break;    case T_HOLDUNTIL:			// set time to send	if (SPACE() && SNPPTime(tv)) {	    if (opt_CRLF()) {		holdCmd(tv);		return (true);	    } else if (string_param(s, "GMT-difference")) {		// conver GMT offset to numeric value		int sign = 1;		const char* cp = s;		if (*cp == '-')		    cp++, sign = -1;		else if (*cp == '+')		    cp++;		time_t off = (time_t) (strtoul(cp, 0, 10)*60 / 100);		holdCmd(tv + sign*off);		return (true);	    }	}	break;    case T_LEVEL:			// set level of operation	if (number_param(n)) {	    logcmd(t, "%lu", n);	    serviceLevel((u_int) n);	    return (true);	}	break;    case T_LOGIN:			// login as user	if (SPACE() && STRING(s, "login-ID")) {	    fxStr pwd;	    if (opt_CRLF()) {		logcmd(t, (const char*) s);		loginCmd(s);		return (true);	    } else if (string_param(pwd, "password")) {		logcmd(t, "%s <passwd>", (const char*) s);		loginCmd(s, pwd);		return (true);	    }	}	break;    case T_MESSAGE:			// specify 1-line message data	if (SPACE() && multi_STRING(s) && CRLF()) {	    logcmd(t, "%s", (const char*) s);	    messageCmd(s);	    return (true);	}	break;    case T_PAGER:			// specify destination pager ID	if (SPACE() && STRING(s, "pager-ID")) {	    fxStr pwd;	    if (opt_CRLF()) {		logcmd(t, "%s", (const char*) s);		pagerCmd(s);		return (true);	    } else if (string_param(pwd, "password/PIN")) {		logcmd(t, "%s <passwd/PIN>", (const char*) s);		pagerCmd(s, pwd);		return (true);	    }	}	break;    case T_PING:			// localize/verify pager ID	if (string_param(s, "pager-ID")) {	    logcmd(t, "%s", (const char*) s);	    pingCmd(s);	    return (true);	}	break;    case T_QUIT:			// terminate session	if (CRLF()) {	    logcmd(t);	    reply(221, "Goodbye.");	    dologout(0);	    return (true);	}	break;    case T_REST:			// reset server state	logcmd(t);	initServer();	reply(220, "%s server (%s) ready.", (const char*) hostname, version);	break;    case T_SEND:			// initiate send operation	if (CRLF()) {	    logcmd(t);	    sendCmd();	    return (true);	}	break;    case T_SITE:			// site-specific command	if (SPACE() && getToken(T_STRING, "site command")) {	    tokenBody.raisecase();	    const tab* p = lookup(sitetab, N(sitetab), tokenBody);	    if (p == NULL) {		reply(500, "SITE %s: Command not recognized.",		    (const char*) tokenBody);	    } else if (!p->implemented)		reply(500, "SITE %s: Command not implemented.", p->name);	    else		return (site_cmd(p->token));	}	break;    case T_STAT:			// server status	if (CRLF()) {	    logcmd(t);	    statusCmd();	    return (true);	}	break;    case T_SUBJECT:			// message subject	if (SPACE() && multi_STRING(s) && CRLF()) {	    logcmd(t, "%s", (const char*) s);	    subjectCmd(s);	    return (true);	}	break;    }    return (false);}/* * Site-specific protocol commands (one line). */boolSNPPServer::site_cmd(Token t){    fxStr s;    long n;    time_t tv;    bool b;    switch (t) {    case T_IDLE:			// set/query idle timeout	if (opt_CRLF()) {	    logcmd(t);	    reply(250, "%u seconds.", idleTimeout);	    return (true);	} else if (number_param(n)) {	    logcmd(t, "%lu", n);	    if ((unsigned)n > maxIdleTimeout && !IS(PRIVILEGED)) {		idleTimeout = maxIdleTimeout;		reply(250, "%lu: Idle timeout too large, set to %u.",		    n, maxIdleTimeout);	    } else {		idleTimeout = (int) n;		reply(250, "Idle timeout set to %u.", idleTimeout);	    }	    return (true);	}	break;    case T_HELP:			// return help	if (opt_CRLF()) {	    helpCmd(sitetab, (char*) NULL);	    return (true);	} else if (string_param(s, "command name")) {	    logcmd(T_SITE, "HELP %s", (const char*) s);	    s.raisecase();	    helpCmd(sitetab, s);	    return (true);	}	break;    case T_JQUEUE:	if (boolean_param(b)) {	    logcmd(t, "%s", b ? "YES" : "NO");	    defJob.queued = b;	    reply(250, "Job will%s be queued.", b ? "" : " not");	    return (true);	}	break;    case T_FROM_USER:    case T_MODEM:    case T_NOTIFY:    case T_NOTIFYADDR:	if (SPACE() && multi_STRING(s) && CRLF() && setJobParameter(defJob, t, s)) {	    logcmd(t, "%s", (const char*) s);	    reply(250, "%s set to \"%s\".", parmToken(t), (const char*) s);	    return (true);	}	break;    case T_MAXDIALS:    case T_MAXTRIES:    case T_SCHEDPRI:	if (number_param(n) && setJobParameter(defJob, t, (u_short) n)) {	    logcmd(t, "%lu", n);	    reply(250, "%s set to %u.", parmToken(t), n);	    return (true);	}	break;    case T_LASTTIME:			// time to kill job	if (timespec_param(6, tv) && setJobParameter(defJob, t, tv)) {	    logcmd(t, "%02d%02d%02d"		, tv/(24*60*60) , (tv/(60*60))%24 , (tv/60)%60);	    reply(250, "%s set to %02d%02d%02d."		, parmToken(t)		, tv/(24*60*60) , (tv/(60*60))%24 , (tv/60)%60);	    return (true);	}	break;    case T_RETRYTIME:			// retry interval for job	if (timespec_param(4, tv) && setJobParameter(defJob, t, tv)) {	    logcmd(t, "%02d%02d" , tv/60, tv%60);	    reply(250, "%s set to %02d%02d.", parmToken(t), tv/60, tv%60);	    return (true);	}	break;    case T_JPARM:			// query job parameters	if (CRLF()) {	    logcmd(t);	    jstatCmd(defJob);	    return (true);	}	break;    }    return (false);}/* * Parse an SNPP time specification. */boolSNPPServer::SNPPTime(time_t& result){    if (getToken(T_STRING, "time specification") && checkNUMBER(tokenBody)) {	u_int tlen = tokenBody.length();	const char* cp = tokenBody;	// YYMMDDHHMM[SS]	if (tlen == 12 || tlen == 10) {	    struct tm tm;	    tm.tm_sec  = (tlen == 12 ? twodigits(cp+10, 60) : 0);	    tm.tm_min  = twodigits(cp+8, 60);	    tm.tm_hour = twodigits(cp+6, 24);	    tm.tm_mday = twodigits(cp+4, 32);	    tm.tm_mon  = twodigits(cp+2, 13) - 1;	    tm.tm_year = twodigits(cp+0, 100);	    /*	     * SNPP botched time specifications by not using 4 digits	     * to specify a year.  This means that we have to guess at	     * the intended year when the value is far in the future	     * (as opposed to a year in the past that was given by	     * mistake).  We arbitrarily assume years prior to 1990	     * are in the next century and adjust them accordingly.	     */	    if (tm.tm_year < 90)		tm.tm_year += 100;	    tm.tm_isdst= -1;		// XXX not sure about this???	    /*	     * The above time is assumed to be relative to	     * GMT and mktime returns locally adjusted time	     * so we need to adjust the result to get things	     * in the right timezone.  Note that any additional	     * timezone correction factor specified by the	     * client will then be applied to this result.	     */	    result = mktime(&tm) - gmtoff;	    return (true);	}	syntaxError(fxStr::format(	    "bad time specification (expecting 10/12 digits, got %u)", tlen));    }    return (false);}voidSNPPServer::syntaxError(const char* msg){    const char* cp = strchr(cbuf, '\0');    if (cp[-1] == '\n')	cp--;    reply(500, "'%.*s': Syntax error, %s.", cp-cbuf, cbuf, msg);}/* * Command support methods. *//* * Process a multi-line text message. */voidSNPPServer::dataCmd(void){    if (!haveText) {	fxStr emsg;	u_int seqnum = getDocumentNumber(emsg);	if (seqnum == (u_int) -1) {	    reply(554, "%s", (const char*)emsg);	    return;	}	msgFile = fxStr::format("/%s/doc%u.page", FAX_TMPDIR, seqnum);	FILE* fout = Sys::fopen(msgFile, "w");	if (fout != NULL) {	    setFileOwner(msgFile);	    FileCache::chmod(msgFile, 0660);		// sync cache	    tempFiles.append(msgFile);	    reply(354, "Begin message input; end with <CRLF>'.'<CRLF>.");	    char buf[1024];	    u_int len = 0;	    for (;;) {		if (getCmdLine(buf, sizeof (buf), true)) {		    const char* bp = buf;		    if (bp[0] == '.') {			if ((bp[1] == '\n' && bp[2] == '\0') || bp[1] == '\0')			    break;			if (bp[1] == '.' && bp[2] == '\0')	// .. -> .			    bp++;		    }		    u_int blen = strlen(bp);		    if ((len += blen) > maxMsgLength) {			reply(550,			    "Error, message too long; max %u characters.",			    maxMsgLength);			(void) fclose(fout);			Sys::unlink(msgFile);			return;		    }		    // if buf only contains .., we skipped the first .		    // hence we must write bp, not buf. also blen is		    // the length of bp, not buf.		    (void) fwrite((const char*) bp, blen, 1, fout);		}	    }	    if (fclose(fout)) {		perror_reply(554, msgFile, errno);		Sys::unlink(msgFile);	    } else {		haveText = true;		reply(250, "Message text OK.");	    }	} else	    perror_reply(554, msgFile, errno);    } else	reply(503, "Error, message already entered.");}/* * Provide help.  We cannot share the base class * implementation of this command because SNPP * defines a different style for responses (sigh). */voidSNPPServer::helpCmd(const tab* ctab, const char* s){    const char* type;    u_int NCMDS;    if (ctab == sitetab) {        type = "SITE ";	NCMDS = N(sitetab);    } else {        type = "";	NCMDS = N(cmdtab);    }    int width = 0;    const tab* c = ctab;    for (u_int n = NCMDS; n != 0; c++, n--) {        int len = strlen(c->name);        if (len > width)            width = len;    }    width = (width + 8) &~ 7;    if (s == NULL) {        reply(214, "The following %scommands are recognized %s.",            type, "(* =>'s unimplemented)");        int columns = 76 / width;        if (columns == 0)            columns = 1;        int lines = (NCMDS + columns - 1) / columns;        for (int i = 0; i < lines; i++) {            printf("214 ");            for (int j = 0; j < columns; j++) {                c = &ctab[j*lines + i];                printf("%s%c", c->name, !c->implemented ? '*' : ' ');                if (c + lines >= &ctab[NCMDS])                    break;                int w = strlen(c->name) + 1;                while (w < width) {                    putchar(' ');                    w++;                }            }            printf("\r\n");        }        (void) fflush(stdout);        reply(250, "Direct comments to %s.", (const char*) faxContact);    } else {	c = lookup(ctab, NCMDS, s);	if (c == NULL)	    reply(550, "Unknown command %s.", s);	else if (c->implemented)	    reply(218, "Syntax: %s%s %s", type, c->name, c->help);	else	    reply(218, "%s%-*s\t%s; unimplemented.",		type, width, c->name, c->help);    }}/* * Specify the hold time (time to send) for a request. */voidSNPPServer::holdCmd(time_t when){

⌨️ 快捷键说明

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