예제 #1
0
eNextState SMTP_C_Shutdown(AsyncIO *IO)
{
	EVS_syslog(LOG_DEBUG, "%s\n", __FUNCTION__);
	SmtpOutMsg *Msg = IO->Data;

	switch (IO->NextState) {
	case eSendDNSQuery:
	case eReadDNSReply:

		/* todo: abort c-ares */
	case eConnect:
	case eSendReply:
	case eSendMore:
	case eSendFile:
	case eReadMessage:
	case eReadMore:
	case eReadPayload:
	case eReadFile:
		StopClientWatchers(IO, 1);
		break;
	case eDBQuery:

		break;
	case eTerminateConnection:
	case eAbort:
		break;
	}
	Msg->MyQEntry->Status = 3;
	StrBufPlain(Msg->MyQEntry->StatusMessage,
		    HKEY("server shutdown during message submit."));
	return FinalizeMessageSend(Msg);
}
예제 #2
0
eNextState SMTPC_send_authplain_2(SmtpOutMsg *Msg)
{
	AsyncIO *IO = &Msg->IO;
	char buf[SIZ];
	char encoded[1024];
	long encodedlen;

	sprintf(buf, "%s",
		Msg->pCurrRelay->Pass);
	
	encodedlen = CtdlEncodeBase64(
		encoded,
		Msg->pCurrRelay->Pass,
		strlen(Msg->pCurrRelay->Pass),
		0);

	if (encoded[encodedlen - 1] == '\n') {
		encodedlen --;
		encoded[encodedlen] = '\0';
	}

	StrBufPlain(Msg->IO.SendBuf.Buf,
		    encoded,
		    encodedlen);

	StrBufAppendBufPlain(Msg->IO.SendBuf.Buf,
			     HKEY("\r\n"), 0);

	SMTP_DBG_SEND();

	return eReadMessage;
}
예제 #3
0
eNextState POP3_C_DNSFail(AsyncIO *IO)
{
	pop3aggr *pMsg = (pop3aggr *)IO->Data;

	EVP3CCS_syslog(LOG_DEBUG, "POP3: %s\n", __FUNCTION__);
	StrBufPlain(IO->ErrMsg, CKEY(POP3C_ReadErrors[pMsg->State]));
	return FailAggregationRun(IO);
}
예제 #4
0
eNextState SMTPC_send_QUIT(SmtpOutMsg *Msg)
{
	AsyncIO *IO = &Msg->IO;
	StrBufPlain(Msg->IO.SendBuf.Buf,
		    HKEY("QUIT\r\n"));

	SMTP_DBG_SEND();
	return eReadMessage;
}
예제 #5
0
eNextState POP3C_SendListCommand(pop3aggr *RecvMsg)
{
	AsyncIO *IO = &RecvMsg->IO;
	SetPOP3State(IO, eListing);

	/* Get the list of messages */
	StrBufPlain(RecvMsg->IO.SendBuf.Buf, HKEY("LIST\r\n"));
	POP3C_DBG_SEND();
	return eReadMessage;
}
예제 #6
0
eNextState SMTPC_send_DATAcmd(SmtpOutMsg *Msg)
{
	AsyncIO *IO = &Msg->IO;
	/* RCPT succeeded, now try the DATA command */
	StrBufPlain(Msg->IO.SendBuf.Buf,
		    HKEY("DATA\r\n"));

	SMTP_DBG_SEND();
	return eReadMessage;
}
예제 #7
0
eNextState POP3C_SendQuit(pop3aggr *RecvMsg)
{
	AsyncIO *IO = &RecvMsg->IO;
	SetPOP3State(IO, eQuit);

	/* Log out */
	StrBufPlain(RecvMsg->IO.SendBuf.Buf,
		    HKEY("QUIT\r\n3)"));
	POP3C_DBG_SEND();
	return eReadMessage;
}
예제 #8
0
eNextState SMTPC_send_terminate_data_body(SmtpOutMsg *Msg)
{
	StrBuf *Buf;

	Buf = Msg->IO.SendBuf.Buf;
	Msg->IO.SendBuf.Buf = Msg->msgtext;
	Msg->msgtext = Buf;

	StrBufPlain(Msg->IO.SendBuf.Buf,
		    HKEY(".\r\n"));

	return eReadMessage;

}
예제 #9
0
void OverrideRequest(ParsedHttpHdrs *Hdr, const char *Line, long len)
{
	StrBuf *Buf = NewStrBuf();

	if (Hdr->HR.ReqLine != NULL) {
		FlushStrBuf(Hdr->HR.ReqLine);
		StrBufPlain(Hdr->HR.ReqLine, Line, len);
	}
	else {
		Hdr->HR.ReqLine = NewStrBufPlain(Line, len);
	}
	ReadHttpSubject(Hdr, Hdr->HR.ReqLine, Buf);

	FreeStrBuf(&Buf);
}
예제 #10
0
static void ListCalculateSubject(struct CtdlMessage *msg)
{
	struct CitContext *CCC = CC;
	StrBuf *Subject, *FlatSubject;
	int rlen;
	char *pCh;

	if (CM_IsEmpty(msg, eMsgSubject)) {
		Subject = NewStrBufPlain(HKEY("(no subject)"));
	}
	else {
		Subject = NewStrBufPlain(CM_KEY(msg, eMsgSubject));
	}
	FlatSubject = NewStrBufPlain(NULL, StrLength(Subject));
	StrBuf_RFC822_to_Utf8(FlatSubject, Subject, NULL, NULL);

	rlen = strlen(CCC->room.QRname);
	pCh  = strstr(ChrPtr(FlatSubject), CCC->room.QRname);
	if ((pCh == NULL) ||
	    (*(pCh + rlen) != ']') ||
	    (pCh == ChrPtr(FlatSubject)) ||
	    (*(pCh - 1) != '[')
		)
	{
		StrBuf *tmp;
		StrBufPlain(Subject, HKEY("["));
		StrBufAppendBufPlain(Subject,
				     CCC->room.QRname,
				     rlen, 0);
		StrBufAppendBufPlain(Subject, HKEY("] "), 0);
		StrBufAppendBuf(Subject, FlatSubject, 0);
		/* so we can free the right one swap them */
		tmp = Subject;
		Subject = FlatSubject;
		FlatSubject = tmp;
		StrBufRFC2047encode(&Subject, FlatSubject);
	}

	CM_SetAsFieldSB(msg, eMsgSubject, &Subject);

	FreeStrBuf(&FlatSubject);
}
예제 #11
0
eNextState SMTPC_read_data_body_reply(SmtpOutMsg *Msg)
{
	AsyncIO *IO = &Msg->IO;
	SMTP_DBG_READ();

	if (!SMTP_IS_STATE('2')) {
		if (SMTP_IS_STATE('4'))
			SMTP_VERROR(4);
		else
			SMTP_VERROR(5);
	}

	SetSMTPState(IO, eSTMPsmtpdone);
	/* We did it! */
	StrBufPlain(Msg->MyQEntry->StatusMessage,
		    &ChrPtr(Msg->IO.RecvBuf.Buf)[4],
		    StrLength(Msg->IO.RecvBuf.Buf) - 4);
	StrBufTrim(Msg->MyQEntry->StatusMessage);
	Msg->MyQEntry->Status = 2;
	return eSendReply;
}
예제 #12
0
eNextState SMTPC_send_auth(SmtpOutMsg *Msg)
{
	AsyncIO *IO = &Msg->IO;
	char buf[SIZ];
	char encoded[1024];

	if ((Msg->pCurrRelay == NULL) ||
	    (Msg->pCurrRelay->User == NULL))
		READ_NEXT_STATE(eFROM); /* Skip auth, shouldn't even come here!... */
	else {
		/* Do an AUTH command if necessary */
		if (Msg->SendLogin)
		{
			StrBufPlain(Msg->IO.SendBuf.Buf,
				    HKEY("AUTH LOGIN\r\n"));
		}
		else
		{
			sprintf(buf, "%s%c%s%c%s",
				Msg->pCurrRelay->User, '\0',
				Msg->pCurrRelay->User, '\0',
				Msg->pCurrRelay->Pass);
			
			size_t len = CtdlEncodeBase64(encoded, buf,
						      strlen(Msg->pCurrRelay->User) * 2 +
						      strlen(Msg->pCurrRelay->Pass) + 2, 0);

			if (buf[len - 1] == '\n') {
				buf[len - 1] = '\0';
			}

			StrBufPrintf(Msg->IO.SendBuf.Buf,
				     "AUTH PLAIN %s\r\n",
				     encoded);
		}
	}
	SMTP_DBG_SEND();
	return eReadMessage;
}
예제 #13
0
void smtp_try_one_queue_entry(OneQueItem *MyQItem,
			      MailQEntry *MyQEntry,
			      StrBuf *MsgText,
			/*KeepMsgText allows us to use MsgText as ours.*/
			      int KeepMsgText,
			      int MsgCount)
{
	SmtpOutMsg *Msg;

	SMTPC_syslog(LOG_DEBUG, "%s\n", __FUNCTION__);

	Msg = new_smtp_outmsg(MyQItem, MyQEntry, MsgCount);
	if (Msg == NULL) {
		SMTPC_syslog(LOG_DEBUG, "%s Failed to alocate message context.\n", __FUNCTION__);
		if (KeepMsgText) 
			FreeStrBuf (&MsgText);
		return;
	}
	if (KeepMsgText) Msg->msgtext = MsgText;
	else		 Msg->msgtext = NewStrBufDup(MsgText);

	if (smtp_resolve_recipients(Msg) &&
	    (!MyQItem->HaveRelay ||
	     (MyQItem->URL != NULL)))
	{
		safestrncpy(
			((CitContext *)Msg->IO.CitContext)->cs_host,
			Msg->node,
			sizeof(((CitContext *)
				Msg->IO.CitContext)->cs_host));

		SMTPC_syslog(LOG_DEBUG, "Starting: [%ld] <%s> CC <%d> \n",
			     Msg->MyQItem->MessageID,
			     ChrPtr(Msg->MyQEntry->Recipient),
			     ((CitContext*)Msg->IO.CitContext)->cs_pid);
		if (Msg->pCurrRelay == NULL) {
			SetSMTPState(&Msg->IO, eSTMPmxlookup);
			QueueEventContext(&Msg->IO,
					  resolve_mx_records);
		}
		else { /* oh... via relay host */
			Msg->IsRelay = 1;
			if (Msg->pCurrRelay->IsIP) {
				SetSMTPState(&Msg->IO, eSTMPconnecting);
				QueueEventContext(&Msg->IO,
						  mx_connect_ip);
			}
			else {
				SetSMTPState(&Msg->IO, eSTMPalookup);
				/* uneducated admin has chosen to
				   add DNS to the equation... */
				QueueEventContext(&Msg->IO,
						  get_one_mx_host_ip);
			}
		}
	}
	else {
		SetSMTPState(&Msg->IO, eSMTPFailTotal);
		/* No recipients? well fail then. */
		if (Msg->MyQEntry != NULL) {
			Msg->MyQEntry->Status = 5;
			if (StrLength(Msg->MyQEntry->StatusMessage) == 0)
				StrBufPlain(Msg->MyQEntry->StatusMessage,
					    HKEY("Invalid Recipient!"));
		}
		FinalizeMessageSend_DB(&Msg->IO);
		DeleteSmtpOutMsg(Msg);
	}
}
예제 #14
0
static void
IO_recv_callback(struct ev_loop *loop, ev_io *watcher, int revents)
{
	const char *errmsg;
	ssize_t nbytes;
	AsyncIO *IO = watcher->data;

	SET_EV_TIME(IO, event_base);
	switch (IO->NextState) {
	case eReadFile:
		nbytes = FileRecvChunked(&IO->IOB, &errmsg);
		if (nbytes < 0)
			StrBufPlain(IO->ErrMsg, errmsg, -1);
		else
		{
			if (IO->IOB.ChunkSendRemain == 0)
			{
				IO->NextState = eSendReply;
				assert(IO->ReadDone);
				ev_io_stop(event_base, &IO->recv_event);
				PostInbound(IO);
				return;
			}
			else
				return;
		}
		break;
	default:
		nbytes = StrBuf_read_one_chunk_callback(IO->RecvBuf.fd,
							0,
							&IO->RecvBuf);
		break;
	}

#ifdef BIGBAD_IODBG
	{
		long nbytes;
		int rv = 0;
		char fn [SIZ];
		FILE *fd;
		const char *pch = ChrPtr(IO->RecvBuf.Buf);
		const char *pchh = IO->RecvBuf.ReadWritePointer;

		if (pchh == NULL)
			pchh = pch;

		nbytes = StrLength(IO->RecvBuf.Buf) - (pchh - pch);
		snprintf(fn, SIZ, "/tmp/foolog_ev_%s.%d",
			 ((CitContext*)(IO->CitContext))->ServiceName,
			 IO->SendBuf.fd);

		fd = fopen(fn, "a+");
		if (fd == NULL) {
			syslog(LOG_EMERG, "failed to open file %s: %s", fn, strerror(errno));
			cit_backtrace();
			exit(1);
		}
		fprintf(fd, "Read: BufSize: %ld BufContent: [",
			nbytes);
		rv = fwrite(pchh, nbytes, 1, fd);
		if (!rv) printf("failed to write debug to %s!\n", fn);
		fprintf(fd, "]\n");
		fclose(fd);
	}
#endif
	if (nbytes > 0) {
		HandleInbound(IO);
	} else if (nbytes == 0) {
		StopClientWatchers(IO, 1);
		SetNextTimeout(IO, 0.01);
		return;
	} else if (nbytes == -1) {
		if (errno != EAGAIN) {
			// FD is gone. kick it. 
			StopClientWatchers(IO, 1);
			EV_syslog(LOG_DEBUG,
				  "IO_recv_callback(): Socket Invalid! [%d] [%s] [%d]\n",
				  errno, strerror(errno), IO->SendBuf.fd);
			StrBufPrintf(IO->ErrMsg,
				     "Socket Invalid! [%s]",
				     strerror(errno));
			SetNextTimeout(IO, 0.01);
		}
		return;
	}
}
예제 #15
0
static void
IO_send_callback(struct ev_loop *loop, ev_io *watcher, int revents)
{
	int rc;
	AsyncIO *IO = watcher->data;
	const char *errmsg = NULL;

	SET_EV_TIME(IO, event_base);
	become_session(IO->CitContext);
#ifdef BIGBAD_IODBG
	{
		int rv = 0;
		char fn [SIZ];
		FILE *fd;
		const char *pch = ChrPtr(IO->SendBuf.Buf);
		const char *pchh = IO->SendBuf.ReadWritePointer;
		long nbytes;

		if (pchh == NULL)
			pchh = pch;

		nbytes = StrLength(IO->SendBuf.Buf) - (pchh - pch);
		snprintf(fn, SIZ, "/tmp/foolog_ev_%s.%d",
			 ((CitContext*)(IO->CitContext))->ServiceName,
			 IO->SendBuf.fd);

		fd = fopen(fn, "a+");
		if (fd == NULL) {
			syslog(LOG_EMERG, "failed to open file %s: %s", fn, strerror(errno));
			cit_backtrace();
			exit(1);
		}
		fprintf(fd, "Send: BufSize: %ld BufContent: [",
			nbytes);
		rv = fwrite(pchh, nbytes, 1, fd);
		if (!rv) printf("failed to write debug to %s!\n", fn);
		fprintf(fd, "]\n");
#endif
		switch (IO->NextState) {
		case eSendFile:
			rc = FileSendChunked(&IO->IOB, &errmsg);
			if (rc < 0)
				StrBufPlain(IO->ErrMsg, errmsg, -1);
			break;
		default:
			rc = StrBuf_write_one_chunk_callback(IO->SendBuf.fd,
							     0,
							     &IO->SendBuf);
		}

#ifdef BIGBAD_IODBG
		fprintf(fd, "Sent: BufSize: %d bytes.\n", rc);
		fclose(fd);
	}
#endif
	if (rc == 0)
	{
		ev_io_stop(event_base, &IO->send_event);
		switch (IO->NextState) {
		case eSendMore:
			assert(IO->SendDone);
			IO->NextState = IO->SendDone(IO);

			if ((IO->NextState == eTerminateConnection) ||
			    (IO->NextState == eAbort) )
				ShutDownCLient(IO);
			else {
				ev_io_start(event_base, &IO->send_event);
			}
			break;
		case eSendFile:
			if (IO->IOB.ChunkSendRemain > 0) {
				ev_io_start(event_base, &IO->recv_event);
				SetNextTimeout(IO, 100.0);

			} else {
				assert(IO->ReadDone);
				IO->NextState = IO->ReadDone(IO);
				switch(IO->NextState) {
				case eSendDNSQuery:
				case eReadDNSReply:
				case eDBQuery:
				case eConnect:
					break;
				case eSendReply:
				case eSendMore:
				case eSendFile:
					ev_io_start(event_base,
						    &IO->send_event);
					break;
				case eReadMessage:
				case eReadMore:
				case eReadPayload:
				case eReadFile:
					break;
				case eTerminateConnection:
				case eAbort:
					break;
				}
			}
			break;
		case eSendReply:
		    if (StrBufCheckBuffer(&IO->SendBuf) != eReadSuccess)
			break;
		    IO->NextState = eReadMore;
		case eReadMore:
		case eReadMessage:
		case eReadPayload:
		case eReadFile:
			if (StrBufCheckBuffer(&IO->RecvBuf) == eBufferNotEmpty)
			{
				HandleInbound(IO);
			}
			else {
				ev_io_start(event_base, &IO->recv_event);
			}

			break;
		case eDBQuery:
			/*
			 * we now live in another queue,
			 * so we have to unregister.
			 */
			ev_cleanup_stop(loop, &IO->abort_by_shutdown);
			break;
		case eSendDNSQuery:
		case eReadDNSReply:
		case eConnect:
		case eTerminateConnection:
		case eAbort:
			break;
		}
	}
	else if (rc < 0) {
		if (errno != EAGAIN) {
			StopClientWatchers(IO, 1);
			EV_syslog(LOG_DEBUG,
				  "IO_send_callback(): Socket Invalid! [%d] [%s] [%d]\n",
				  errno, strerror(errno), IO->SendBuf.fd);
			StrBufPrintf(IO->ErrMsg,
				     "Socket Invalid! [%s]",
				     strerror(errno));
			SetNextTimeout(IO, 0.01);
		}
	}
	/* else : must write more. */
}
예제 #16
0
void render_MIME_ICS_TPL(StrBuf *Target, WCTemplputParams *TP, StrBuf *FoundCharset)
{
	wc_mime_attachment *Mime = CTX(CTX_MIME_ATACH);
	icalproperty_method the_method = ICAL_METHOD_NONE;
	icalproperty *method = NULL;
	icalcomponent *cal = NULL;
	icalcomponent *c = NULL;
        WCTemplputParams SubTP;
        WCTemplputParams SuperTP;

	static int divcount = 0;

	if (StrLength(Mime->Data) == 0) {
		MimeLoadData(Mime);
	}
	if (StrLength(Mime->Data) > 0) {
		cal = icalcomponent_new_from_string(ChrPtr(Mime->Data));
	}
	if (cal == NULL) {
		StrBufAppendPrintf(Mime->Data, _("There was an error parsing this calendar item."));
		StrBufAppendPrintf(Mime->Data, "<br>\n");
		return;
	}

	putlbstr("divname",  ++divcount);


	putbstr("cal_partnum", NewStrBufDup(Mime->PartNum));
	putlbstr("msgnum", Mime->msgnum);

        memset(&SubTP, 0, sizeof(WCTemplputParams));
        memset(&SuperTP, 0, sizeof(WCTemplputParams));

	/*//ical_dezonify(cal); */

	/* If the component has subcomponents, recurse through them. */
	c = icalcomponent_get_first_component(cal, ICAL_ANY_COMPONENT);
        c = (c != NULL) ? c : cal;

	method = icalcomponent_get_first_property(cal, ICAL_METHOD_PROPERTY);
	if (method != NULL) {
		the_method = icalproperty_get_method(method);
	}

	StackContext (TP,
		      &SuperTP,
		      &the_method,
		      CTX_ICALMETHOD,
		      0,
		      TP->Tokens);

	StackContext (&SuperTP, 
		      &SubTP, 
		      c,
		      CTX_ICAL,
		      0,
		      SuperTP.Tokens);
	FlushStrBuf(Mime->Data);
///	DoTemplate(HKEY("ical_attachment_display"), Mime->Data, &SubTP);
	DoTemplate(HKEY("ical_edit"), Mime->Data, &SubTP);

	/*/ cal_process_object(Mime->Data, cal, 0, Mime->msgnum, ChrPtr(Mime->PartNum)); */

	/* Free the memory we obtained from libical's constructor */
	StrBufPlain(Mime->ContentType, HKEY("text/html"));
	StrBufAppendPrintf(WC->trailing_javascript,
		"eventEditAllDay();		\n"
		"RecurrenceShowHide();		\n"
		"EnableOrDisableCheckButton();	\n"
	);

	UnStackContext(&SuperTP);
	UnStackContext(&SubTP);
	icalcomponent_free(cal);
}
예제 #17
0
/* 
 * Locate a <link> tag and, given its 'rel=' parameter, return its 'href' parameter
 */
void extract_link(StrBuf *target_buf, const char *rel, long repllen, StrBuf *source_buf)
{
	int i;
	const char *ptr;
	const char *href_start = NULL;
	const char *href_end = NULL;
	const char *link_tag_start = NULL;
	const char *link_tag_end = NULL;
	const char *rel_start = NULL;
	const char *rel_end = NULL;

	if (!target_buf) return;
	if (!rel) return;
	if (!source_buf) return;

	ptr = ChrPtr(source_buf);

	FlushStrBuf(target_buf);
	while (ptr = cbmstrcasestr(ptr, "<link"), ptr != NULL) {

		link_tag_start = ptr;
		link_tag_end = strchr(ptr, '>');
		if (link_tag_end == NULL)
			break;
		for (i=0; i < 1; i++ ){
			rel_start = cbmstrcasestr(link_tag_start, "rel=");
			if ((rel_start == NULL) ||
			    (rel_start > link_tag_end)) 
				continue;

			rel_start = strchr(rel_start, '\"');
			if ((rel_start == NULL) ||
			    (rel_start > link_tag_end)) 
				continue;
			++rel_start;
			rel_end = strchr(rel_start, '\"');
			if ((rel_end == NULL) ||
			    (rel_end == rel_start) ||
			    (rel_end >= link_tag_end) ) 
				continue;
			if (strncasecmp(rel, rel_start, repllen)!= 0)
				continue; /* didn't match? never mind... */
			
			href_start = cbmstrcasestr(link_tag_start, "href=");
			if ((href_start == NULL) || 
			    (href_start >= link_tag_end)) 
				continue;
			href_start = strchr(href_start, '\"');
			if ((href_start == NULL) |
			    (href_start >= link_tag_end)) 
				continue;
			++href_start;
			href_end = strchr(href_start, '\"');
			if ((href_end == NULL) || 
			    (href_end == href_start) ||
			    (href_start >= link_tag_end)) 
				continue;
			StrBufPlain(target_buf, href_start, href_end - href_start);
		}
		ptr = link_tag_end;	
	}
}
예제 #18
0
int ReadHttpSubject(ParsedHttpHdrs *Hdr, StrBuf *Line, StrBuf *Buf)
{
	const char *Args;
	void *vLine, *vHandler;
	const char *Pos = NULL;

	Hdr->HR.ReqLine = Line;
	/* The requesttype... GET, POST... */
	StrBufExtract_token(Buf, Hdr->HR.ReqLine, 0, ' ');
	if (GetHash(HttpReqTypes, SKEY(Buf), &vLine) &&
	    (vLine != NULL))
	{
		Hdr->HR.eReqType = *(long*)vLine;
	}
	else {
		Hdr->HR.eReqType = eGET;
		return 1;
	}
	StrBufCutLeft(Hdr->HR.ReqLine, StrLength(Buf) + 1);

	/* the HTTP Version... */
	StrBufExtract_token(Buf, Hdr->HR.ReqLine, 1, ' ');
	StrBufCutRight(Hdr->HR.ReqLine, StrLength(Buf) + 1);
	
	if (StrLength(Buf) == 0) {
		Hdr->HR.eReqType = eGET;
		return 1;
	}

	StrBufAppendBuf(Hdr->this_page, Hdr->HR.ReqLine, 0);

	/* chop Filename / query arguments */
	Args = strchr(ChrPtr(Hdr->HR.ReqLine), '?');
	if (Args == NULL) /* whe're not that picky about params... TODO: this will spoil '&' in filenames.*/
		Args = strchr(ChrPtr(Hdr->HR.ReqLine), '&');
	if (Args != NULL) {
		Args ++; /* skip the ? */
		StrBufPlain(Hdr->PlainArgs, 
			    Args, 
			    StrLength(Hdr->HR.ReqLine) -
			    (Args - ChrPtr(Hdr->HR.ReqLine)));
		StrBufCutAt(Hdr->HR.ReqLine, 0, Args - 1);
	} /* don't parse them yet, maybe we don't even care... */
	
	/* now lookup what we are going to do with this... */
	/* skip first slash */
	StrBufExtract_NextToken(Buf, Hdr->HR.ReqLine, &Pos, '/');
	do {
		StrBufExtract_NextToken(Buf, Hdr->HR.ReqLine, &Pos, '/');

		GetHash(HandlerHash, SKEY(Buf), &vHandler),
		Hdr->HR.Handler = (WebcitHandler*) vHandler;
		if (Hdr->HR.Handler == NULL)
			break;
		/*
		 * If the request is prefixed by "/webcit" then chop that off.  This
		 * allows a front end web server to forward all /webcit requests to us
		 * while still using the same web server port for other things.
		 */
		if ((Hdr->HR.Handler->Flags & URLNAMESPACE) != 0)
			continue;
		break;
	} while (1);
	/* remove the handlername from the URL */
	if ((Pos != NULL) && (Pos != StrBufNOTNULL)){
		StrBufCutLeft(Hdr->HR.ReqLine, 
			      Pos - ChrPtr(Hdr->HR.ReqLine));
	}

	if (Hdr->HR.Handler != NULL) {
		if ((Hdr->HR.Handler->Flags & BOGUS) != 0) {
			return 1;
		}
		Hdr->HR.DontNeedAuth = (
			((Hdr->HR.Handler->Flags & ISSTATIC) != 0) ||
			((Hdr->HR.Handler->Flags & ANONYMOUS) != 0)
		);
	}
	else {
		/* If this is a "flat" request for the root, display the configured landing page. */
		int return_value;
		StrBuf *NewLine = NewStrBuf();
		Hdr->HR.DontNeedAuth = 1;
		StrBufAppendPrintf(NewLine, "GET /landing?go=%s?failvisibly=1 HTTP/1.0", ChrPtr(Buf));
		if (verbose) syslog(LOG_DEBUG, "Replacing with: %s", ChrPtr(NewLine));
		return_value = ReadHttpSubject(Hdr, NewLine, Buf);
		FreeStrBuf(&NewLine);
		return return_value;
	}

	return 0;
}