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); }
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; }
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); }
eNextState SMTPC_send_QUIT(SmtpOutMsg *Msg) { AsyncIO *IO = &Msg->IO; StrBufPlain(Msg->IO.SendBuf.Buf, HKEY("QUIT\r\n")); SMTP_DBG_SEND(); return eReadMessage; }
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; }
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; }
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; }
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; }
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); }
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); }
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; }
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; }
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); } }
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; } }
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. */ }
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); }
/* * 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; } }
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; }