return(0);
}
+/*
+ * qsort() compatible function to compare two longs in descending order.
+ */
+int qlongcmp_r(const void *s1, const void *s2) {
+ long l1 = (long) s1;
+ long l2 = (long) s2;
+
+ if (l1 > l2) return(-1);
+ if (l1 < l2) return(+1);
+ return(0);
+}
+
/*
* qsort() compatible function to compare two message summary structs by ascending subject.
-
-/*
- * Look for URL's embedded in a buffer and make them linkable. We use a
- * target window in order to keep the Citadel session in its own window.
- */
-void UrlizeText(StrBuf* Target, StrBuf *Source, StrBuf *WrkBuf)
-{
- int len, UrlLen, Offset, TrailerLen;
- const char *start, *end, *pos;
-
- FlushStrBuf(Target);
-
- start = NULL;
- len = StrLength(Source);
- end = ChrPtr(Source) + len;
- for (pos = ChrPtr(Source); (pos < end) && (start == NULL); ++pos) {
- if (!strncasecmp(pos, "http://", 7))
- start = pos;
- if (!strncasecmp(pos, "ftp://", 6))
- start = pos;
- }
-
- if (start == NULL) {
- StrBufAppendBuf(Target, Source, 0);
- return;
- }
- FlushStrBuf(WrkBuf);
-
- for (pos = ChrPtr(Source) + len; pos > start; --pos) {
- if ( (!isprint(*pos))
- || (isspace(*pos))
- || (*pos == '{')
- || (*pos == '}')
- || (*pos == '|')
- || (*pos == '\\')
- || (*pos == '^')
- || (*pos == '[')
- || (*pos == ']')
- || (*pos == '`')
- || (*pos == '<')
- || (*pos == '>')
- || (*pos == '(')
- || (*pos == ')')
- ) {
- end = pos;
- }
- }
-
- UrlLen = end - start;
- StrBufAppendBufPlain(WrkBuf, start, UrlLen, 0);
-
- Offset = start - ChrPtr(Source);
- if (Offset != 0)
- StrBufAppendBufPlain(Target, ChrPtr(Source), Offset, 0);
- StrBufAppendPrintf(Target, "%ca href=%c%s%c TARGET=%c%s%c%c%s%c/A%c",
- LB, QU, ChrPtr(WrkBuf), QU, QU, TARGET,
- QU, RB, ChrPtr(WrkBuf), LB, RB);
-
- TrailerLen = len - (end - start);
- if (TrailerLen > 0)
- StrBufAppendBufPlain(Target, end, TrailerLen, 0);
-}
-void url(char *buf, size_t bufsize)
-{
- int len, UrlLen, Offset, TrailerLen, outpos;
- char *start, *end, *pos;
- char urlbuf[SIZ];
- char outbuf[SIZ];
-
- start = NULL;
- len = strlen(buf);
- if (len > bufsize) {
- lprintf(1, "URL: content longer than buffer!");
- return;
- }
- end = buf + len;
- for (pos = buf; (pos < end) && (start == NULL); ++pos) {
- if (!strncasecmp(pos, "http://", 7))
- start = pos;
- if (!strncasecmp(pos, "ftp://", 6))
- start = pos;
- }
-
- if (start == NULL)
- return;
-
- for (pos = buf+len; pos > start; --pos) {
- if ( (!isprint(*pos))
- || (isspace(*pos))
- || (*pos == '{')
- || (*pos == '}')
- || (*pos == '|')
- || (*pos == '\\')
- || (*pos == '^')
- || (*pos == '[')
- || (*pos == ']')
- || (*pos == '`')
- || (*pos == '<')
- || (*pos == '>')
- || (*pos == '(')
- || (*pos == ')')
- ) {
- end = pos;
- }
- }
-
- UrlLen = end - start;
- if (UrlLen > sizeof(urlbuf)){
- lprintf(1, "URL: content longer than buffer!");
- return;
- }
- memcpy(urlbuf, start, UrlLen);
- urlbuf[UrlLen] = '\0';
-
- Offset = start - buf;
- if ((Offset != 0) && (Offset < sizeof(outbuf)))
- memcpy(outbuf, buf, Offset);
- outpos = snprintf(&outbuf[Offset], sizeof(outbuf) - Offset,
- "%ca href=%c%s%c TARGET=%c%s%c%c%s%c/A%c",
- LB, QU, urlbuf, QU, QU, TARGET, QU, RB, urlbuf, LB, RB);
- if (outpos >= sizeof(outbuf) - Offset) {
- lprintf(1, "URL: content longer than buffer!");
- return;
- }
-
- TrailerLen = len - (end - start);
- if (TrailerLen > 0)
- memcpy(outbuf + Offset + outpos, end, TrailerLen);
- if (Offset + outpos + TrailerLen > bufsize) {
- lprintf(1, "URL: content longer than buffer!");
- return;
- }
- memcpy (buf, outbuf, Offset + outpos + TrailerLen);
- *(buf + Offset + outpos + TrailerLen) = '\0';
-}
-
-
-
-
-
-
-
-
-
-
-
/*
* I wanna SEE that message!
*
* printable_view Nonzero to display a printable view
* section Optional for encapsulated message/rfc822 submessage
*/
-void read_message(long msgnum, int printable_view, char *section) {
- struct wcsession *WCC = WC;
+int read_message(StrBuf *Target, const char *tmpl, long tmpllen, long msgnum, int printable_view, const StrBuf *PartNum) {
StrBuf *Buf;
StrBuf *Token;
StrBuf *FoundCharset;
+ HashPos *it;
+ void *vMime;
message_summary *Msg = NULL;
headereval *Hdr;
void *vHdr;
char buf[SIZ];
- struct attach_link *attach_links = NULL;
- int num_attach_links = 0;
// char mime_submessages[256] = "";
char reply_references[1024] = "";
- int i = 0;
int Done = 0;
int state=0;
- char vcard_partnum[256] = "";
- char cal_partnum[256] = "";
- char *part_source = NULL;
- char msg4_partnum[32] = "";
-
-//// strcpy(mime_submessages, "");
+ long len;
+ const char *Key;
Buf = NewStrBuf();
- serv_printf("MSG4 %ld|%s", msgnum, section);
+ lprintf(1, "----------%s---------MSG4 %ld|%s--------------\n", tmpl, msgnum, ChrPtr(PartNum));
+ serv_printf("MSG4 %ld|%s", msgnum, ChrPtr(PartNum));
StrBuf_ServGetln(Buf);
if (GetServerStatus(Buf, NULL) != 1) {
- wprintf("<strong>");
- wprintf(_("ERROR:"));
- wprintf("</strong> %s<br />\n", &buf[4]);
+ StrBufAppendPrintf(Target, "<strong>");
+ StrBufAppendPrintf(Target, _("ERROR:"));
+ StrBufAppendPrintf(Target, "</strong> %s<br />\n", &buf[4]);
FreeStrBuf(&Buf);
- return;
+ return 0;
}
- svputlong("MsgPrintable", printable_view);
+
/** begin everythingamundo table */
Msg = (message_summary *)malloc(sizeof(message_summary));
memset(Msg, 0, sizeof(message_summary));
Msg->msgnum = msgnum;
+ Msg->PartNum = PartNum;
+ Msg->MsgBody = (wc_mime_attachment*) malloc(sizeof(wc_mime_attachment));
+ memset(Msg->MsgBody, 0, sizeof(wc_mime_attachment));
FoundCharset = NewStrBuf();
while ((StrBuf_ServGetln(Buf)>=0) && !Done) {
if ( (StrLength(Buf)==3) &&
{
Done = 1;
if (state < 2) {
- wprintf("<i>");
- wprintf(_("unexpected end of message"));
- wprintf(" (1)</i><br /><br />\n");
- wprintf("</div>\n");
+ lprintf(1, _("unexpected end of message"));
+ StrBufAppendPrintf(Target, "<i>");
+ StrBufAppendPrintf(Target, _("unexpected end of message"));
+ StrBufAppendPrintf(Target, " (1)</i><br /><br />\n");
+ StrBufAppendPrintf(Target, "</div>\n");
FreeStrBuf(&Buf);
FreeStrBuf(&Token);
DestroyMessageSummary(Msg);
FreeStrBuf(&FoundCharset);
- return;
+ return 0;
}
else {
break;
case 1:/* Message Mime Header */
if (StrLength(Buf) == 0) {
state++;
- if (Msg->MsgBody.ContentType == NULL)
+ if (Msg->MsgBody->ContentType == NULL)
/* end of header or no header? */
- Msg->MsgBody.ContentType = NewStrBufPlain(HKEY("text/plain"));
+ Msg->MsgBody->ContentType = NewStrBufPlain(HKEY("text/plain"));
/* usual end of mime header */
}
else
}
case 2: /* Message Body */
- if (Msg->MsgBody.size_known > 0) {
- StrBuf_ServGetBLOB(Msg->MsgBody.Data, Msg->MsgBody.length);
+ if (Msg->MsgBody->size_known > 0) {
+ StrBuf_ServGetBLOB(Msg->MsgBody->Data, Msg->MsgBody->length);
state ++;
/// todo: check next line, if not 000, append following lines
}
else if (1){
- if (StrLength(Msg->MsgBody.Data) > 0)
- StrBufAppendBufPlain(Msg->MsgBody.Data, "\n", 1, 0);
- StrBufAppendBuf(Msg->MsgBody.Data, Buf, 0);
+ if (StrLength(Msg->MsgBody->Data) > 0)
+ StrBufAppendBufPlain(Msg->MsgBody->Data, "\n", 1, 0);
+ StrBufAppendBuf(Msg->MsgBody->Data, Buf, 0);
}
break;
case 3:
- StrBufAppendBuf(Msg->MsgBody.Data, Buf, 0);
+ StrBufAppendBuf(Msg->MsgBody->Data, Buf, 0);
break;
}
}
+
+ if (Msg->AllAttach == NULL)
+ Msg->AllAttach = NewHash(1,NULL);
+ Put(Msg->AllAttach, SKEY(Msg->MsgBody->PartNum), Msg->MsgBody, DestroyMime);
+
/* strip the bare contenttype, so we ommit charset etc. */
- StrBufExtract_token(Buf, Msg->MsgBody.ContentType, 0, ';');
+ StrBufExtract_token(Buf, Msg->MsgBody->ContentType, 0, ';');
StrBufTrim(Buf);
if (GetHash(MimeRenderHandler, SKEY(Buf), &vHdr) &&
(vHdr != NULL)) {
RenderMimeFunc Render;
Render = (RenderMimeFunc)vHdr;
- Render(&Msg->MsgBody, NULL, FoundCharset);
+ Render(Msg->MsgBody, NULL, FoundCharset);
}
-
if (StrLength(Msg->reply_references)> 0) {
/* Trim down excessively long lists of thread references. We eliminate the
* second one in the list so that the thread root remains intact.
StrBufAppendBuf(Msg->reply_to, Msg->from, 0);
}
}
- DoTemplate(HKEY("view_message"), NULL, Msg, CTX_MAILSUM);
-
-
-
-//// put message renderer lookup here.
-///ENDBODY: /* If there are attached submessages, display them now... */
-///
-/// if ( (!IsEmptyStr(mime_submessages)) && (!section[0]) ) {
-/// for (i=0; i<num_tokens(mime_submessages, '|'); ++i) {
-/// extract_token(buf, mime_submessages, i, '|', sizeof buf);
-/// /** use printable_view to suppress buttons */
-/// wprintf("<blockquote>");
-/// read_message(msgnum, 1, buf);
-/// wprintf("</blockquote>");
-/// }
-/// }
-
-
- /* Afterwards, offer links to download attachments 'n' such */
- if ( (num_attach_links > 0) && (!section[0]) ) {
- for (i=0; i<num_attach_links; ++i) {
- if (strcasecmp(attach_links[i].partnum, msg4_partnum)) {
- wprintf("%s", attach_links[i].html);
- }
- }
- }
-
- /* Handler for vCard parts */
- if (!IsEmptyStr(vcard_partnum)) {
- part_source = load_mimepart(msgnum, vcard_partnum);
- if (part_source != NULL) {
-
- /** If it's my vCard I can edit it */
- if ( (!strcasecmp(WC->wc_roomname, USERCONFIGROOM))
- || (!strcasecmp(&WC->wc_roomname[11], USERCONFIGROOM))
- || (WC->wc_view == VIEW_ADDRESSBOOK)
- ) {
- wprintf("<a href=\"edit_vcard?msgnum=%ld&partnum=%s\">",
- msgnum, vcard_partnum);
- wprintf("[%s]</a>", _("edit"));
- }
-
- /* In all cases, display the full card */
- display_vcard(WC->WBuf, part_source, 0, 1, NULL,msgnum);
- }
- }
-
- /* Handler for calendar parts */
- if (!IsEmptyStr(cal_partnum)) {
- }
-
- if (part_source) {
- free(part_source);
- part_source = NULL;
+ it = GetNewHashPos();
+ while (GetNextHashPos(Msg->AllAttach, it, &len, &Key, &vMime) &&
+ (vMime != NULL)) {
+ wc_mime_attachment *Mime = (wc_mime_attachment*) vMime;
+ evaluate_mime_part(Msg, Mime);
}
+ DeleteHashPos(&it);
- wprintf("</div>\n");
-
- /* end everythingamundo table */
- if (!printable_view) {
- wprintf("</div>\n");
- }
+ DoTemplate(tmpl, tmpllen, Target, Msg, CTX_MAILSUM);
- if (num_attach_links > 0) {
- free(attach_links);
- }
DestroyMessageSummary(Msg);
FreeStrBuf(&FoundCharset);
FreeStrBuf(&Token);
FreeStrBuf(&Buf);
+ return 1;
}
*/
void embed_message(void) {
long msgnum = 0L;
+ const StrBuf *Tmpl = sbstr("template");
msgnum = StrTol(WC->UrlFragment1);
- read_message(msgnum, 0, "");
+ if (StrLength(Tmpl) > 0)
+ read_message(WC->WBuf, SKEY(Tmpl), msgnum, 0, NULL);
+ else
+ read_message(WC->WBuf, HKEY("view_message"), msgnum, 0, NULL);
}
output_headers(0, 0, 0, 0, 0, 0);
hprintf("Content-type: text/html\r\n"
- "Server: %s\r\n"
- "Connection: close\r\n",
- PACKAGE_STRING);
+ "Server: " PACKAGE_STRING "\r\n"
+ "Connection: close\r\n");
+
begin_burst();
- wprintf("\r\n<html>\n<head><title>");
- escputs(WC->wc_fullname);
- wprintf("</title></head>\n"
- "<body onLoad=\" window.print(); window.close(); \">\n"
- );
-
- read_message(msgnum, 1, "");
+ read_message(WC->WBuf, HKEY("view_message_print"), msgnum, 1, NULL);
- wprintf("\n</body></html>\n\n");
wDumpContent(0);
}
output_headers(1, 0, 0, 0, 0, 1);
begin_burst();
do_template("msgcontrols", NULL);
- read_message(msgnum,1, "");
+ read_message(WC->WBuf, HKEY("view_message"), msgnum,1, NULL);
wDumpContent(0);
}
* \param forward_attachments Nonzero if we want attachments to be forwarded
*/
void pullquote_message(long msgnum, int forward_attachments, int include_headers) {
+ struct wcsession *WCC = WC;
char buf[SIZ];
char mime_partnum[256];
char mime_filename[256];
char *attachments = NULL;
char *ptr = NULL;
int num_attachments = 0;
- struct wc_attachment *att, *aptr;
+ wc_attachment *att;
char m_subject[1024];
char from[256];
char node[256];
if ( (!strcasecmp(mime_disposition, "inline"))
|| (!strcasecmp(mime_disposition, "attachment")) ) {
+ int n;
+ char N[64];
/* Create an attachment struct from this mime part... */
- att = malloc(sizeof(struct wc_attachment));
- memset(att, 0, sizeof(struct wc_attachment));
+ att = malloc(sizeof(wc_attachment));
+ memset(att, 0, sizeof(wc_attachment));
att->length = mime_length;
- strcpy(att->content_type, mime_content_type);
- strcpy(att->filename, mime_filename);
- att->next = NULL;
+ att->content_type = NewStrBufPlain(mime_content_type, -1);
+ att->filename = NewStrBufPlain(mime_filename, -1);
att->data = load_mimepart(msgnum, mime_partnum);
+ if (WCC->attachments == NULL)
+ WCC->attachments = NewHash(1, NULL);
/* And add it to the list. */
- if (WC->first_attachment == NULL) {
- WC->first_attachment = att;
- }
- else {
- aptr = WC->first_attachment;
- while (aptr->next != NULL) aptr = aptr->next;
- aptr->next = att;
- }
+ n = snprintf(N, sizeof N, "%d", GetCount(WCC->attachments) + 1);
+ Put(WCC->attachments, N, n, att, free_attachment);
}
}
-void EvaluateMimePart(message_summary *Sum, StrBuf *Buf)
-{//// paert=; TODO
-/*
- extract_token(mime_filename, &buf[5], 1, '|', sizeof mime_filename);
- extract_token(mime_partnum, &buf[5], 2, '|', sizeof mime_partnum);
- extract_token(mime_disposition, &buf[5], 3, '|', sizeof mime_disposition);
- extract_token(mime_content_type, &buf[5], 4, '|', sizeof mime_content_type);
- mime_length = extract_int(&buf[5], 5);
-
- if ( (!strcasecmp(mime_content_type, "text/x-vcard"))
- || (!strcasecmp(mime_content_type, "text/vcard")) ) {
- strcpy(vcard_partnum, mime_partnum);
- }
-*/
-}
-
message_summary *ReadOneMessageSummary(StrBuf *RawMessage, const char *DefaultSubject, long MsgNum)
{
void *vEval;
/** Output loop */
if (displayed_msgs != NULL) {
if (bbs_reverse) {
- qsort(displayed_msgs, num_displayed, sizeof(long), longcmp_r);
+ qsort(displayed_msgs, num_displayed, sizeof(long), qlongcmp_r);
}
/** if we do a split bbview in the future, begin messages div here */
for (a=0; a<num_displayed; ++a) {
- read_message(displayed_msgs[a], 0, "");
+ read_message(WC->WBuf, HKEY("view_message"), displayed_msgs[a], 0, NULL);
}
/** if we do a split bbview in the future, end messages div here */
* ... this is where the actual message gets transmitted to the server.
*/
void post_mime_to_server(void) {
+ struct wcsession *WCC = WC;
char top_boundary[SIZ];
char alt_boundary[SIZ];
int is_multipart = 0;
static int seq = 0;
- struct wc_attachment *att;
+ wc_attachment *att;
char *encoded;
size_t encoded_length;
size_t encoded_strlen;
serv_puts("X-Mailer: " PACKAGE_STRING);
/* If there are attachments, we have to do multipart/mixed */
- if (WC->first_attachment != NULL) {
+ if (GetCount(WCC->attachments) > 0) {
is_multipart = 1;
}
serv_printf("--%s--", alt_boundary);
if (is_multipart) {
+ long len;
+ const char *Key;
+ void *vAtt;
+ HashPos *it;
/* Add in the attachments */
- for (att = WC->first_attachment; att!=NULL; att=att->next) {
-
+ it = GetNewHashPos();
+ while (GetNextHashPos(WCC->attachments, it, &len, &Key, &vAtt)) {
+ att = (wc_attachment*)vAtt;
encoded_length = ((att->length * 150) / 100);
encoded = malloc(encoded_length);
if (encoded == NULL) break;
encoded_strlen = CtdlEncodeBase64(encoded, att->data, att->length, 1);
serv_printf("--%s", top_boundary);
- serv_printf("Content-type: %s", att->content_type);
- serv_printf("Content-disposition: attachment; filename=\"%s\"", att->filename);
+ serv_printf("Content-type: %s", ChrPtr(att->content_type));
+ serv_printf("Content-disposition: attachment; filename=\"%s\"", ChrPtr(att->filename));
serv_puts("Content-transfer-encoding: base64");
serv_puts("");
serv_write(encoded, encoded_strlen);
free(encoded);
}
serv_printf("--%s--", top_boundary);
+ DeleteHashPos(&it);
}
serv_puts("000");
char buf[1024];
StrBuf *encoded_subject = NULL;
static long dont_post = (-1L);
- struct wc_attachment *att, *aptr;
+ wc_attachment *att;
int is_anonymous = 0;
const StrBuf *display_name = NULL;
struct wcsession *WCC = WC;
}
if (WCC->upload_length > 0) {
+ const char *pch;
+ int n;
+ char N[64];
lprintf(9, "%s:%d: we are uploading %d bytes\n", __FILE__, __LINE__, WCC->upload_length);
/** There's an attachment. Save it to this struct... */
- att = malloc(sizeof(struct wc_attachment));
- memset(att, 0, sizeof(struct wc_attachment));
+ att = malloc(sizeof(wc_attachment));
+ memset(att, 0, sizeof(wc_attachment));
att->length = WCC->upload_length;
- strcpy(att->content_type, WCC->upload_content_type);
- strcpy(att->filename, WCC->upload_filename);
- att->next = NULL;
-
- /** And add it to the list. */
- if (WCC->first_attachment == NULL) {
- WCC->first_attachment = att;
- }
- else {
- aptr = WCC->first_attachment;
- while (aptr->next != NULL) aptr = aptr->next;
- aptr->next = att;
- }
+ att->content_type = NewStrBufPlain(WCC->upload_content_type, -1);
+ att->filename = NewStrBufPlain(WCC->upload_filename, -1);
+
+
+ if (WCC->attachments == NULL)
+ WCC->attachments = NewHash(1, NULL);
+ /* And add it to the list. */
+ n = snprintf(N, sizeof N, "%d", GetCount(WCC->attachments) + 1);
+ Put(WCC->attachments, N, n, att, free_attachment);
/**
* Mozilla sends a simple filename, which is what we want,
* but Satan's Browser sends an entire pathname. Reduce
* the path to just a filename if we need to.
*/
- while (num_tokens(att->filename, '/') > 1) {
- remove_token(att->filename, 0, '/');
+ pch = strrchr(ChrPtr(att->filename), '/');
+ if (pch != NULL) {
+ StrBufCutLeft(att->filename, pch - ChrPtr(att->filename));
}
- while (num_tokens(att->filename, '\\') > 1) {
- remove_token(att->filename, 0, '\\');
+ pch = strrchr(ChrPtr(att->filename), '\\');
+ if (pch != NULL) {
+ StrBufCutLeft(att->filename, pch - ChrPtr(att->filename));
}
/**
}
}
- free_attachments(WCC);
+ DeleteHash(&WCC->attachments);
/**
* We may have been supplied with instructions regarding the location
StrBuf *ebuf;
long now;
const StrBuf *display_name = NULL;
- struct wc_attachment *att;
+ /////wc_attachment *att;
int recipient_required = 0;
int subject_required = 0;
int recipient_bad = 0;
* Do a custom room banner with no navbar...
*/
output_headers(1, 1, 2, 0, 0, 0);
+
+/*
wprintf("<div id=\"banner\">\n");
embed_room_banner(NULL, navbar_none);
wprintf("</div>\n");
wprintf("<div id=\"content\">\n"
"<div class=\"fix_scrollbar_bug message \">");
-
+*/
/* Now check our actual recipients if there are any */
if (recipient_required) {
const StrBuf *Recp = NULL;
goto DONE;
}
}
+ DoTemplate(HKEY("edit_message"), NULL, NULL, CTX_NONE);
+ address_book_popup();
+ wDumpContent(1);
+
+
+ return;
+
/** If we got this far, we can display the message entry screen. */
wprintf(_("Attachments:"));
wprintf(" ");
wprintf("<select name=\"which_attachment\" size=1>");
+/*
for (att = WCC->first_attachment; att != NULL; att = att->next) {
wprintf("<option value=\"");
urlescputs(att->filename);
wprintf("\">");
escputs(att->filename);
- /* wprintf(" (%s, %d bytes)",att->content_type,att->length); */
+ / * wprintf(" (%s, %d bytes)",att->content_type,att->length); * /
wprintf("</option>\n");
}
+*/
wprintf("</select>");
/** Now offer the ability to attach additional files... */