#line 35 "mailto.c-nw" /* Copyright NBBI, Den Haag, 1994 */ #include #include #include #include #include #include #include #include #include #include #include #define REPLY_NONE 1 #define SUBSCRIBE_METHOD 901 #define UNSUBSCRIBE_METHOD 902 EXPORTDEF(SUBSCRIBE_METHOD) EXPORTDEF(UNSUBSCRIBE_METHOD) #define MAXREPLYSIZE 512 #ifndef MAILCMD #define MAILCMD "mailx -s '%s' %s" /* #define MAILCMD "elm -s %s %s" */ #endif #define min(a, b) ((a) < (b) ? (a) : (b)) typedef struct { char *address; char reply_document[MAXREPLYSIZE]; int reply_offset, reply_size; int flags; int fd; /* Other end of pipe */ Widget to, subject, message; } MailToInfo; static MailToInfo *info[FD_SETSIZE]; #line 88 "mailto.c-nw" static void send_cb(Widget w, XtPointer client_data, XtPointer call_data) { char *subject, mailcmd[1024], *text; int fd = (int) client_data; FILE *f; enter("send_cb\n"); /* Check that the argument is valid */ assert(fd > 2 && info[fd] != NULL); /* Check again, in a different way */ assert(info[fd]->reply_size >= 0 && info[fd]->reply_offset >= 0); assert(XtIsSubclass(XtParent(XtParent(w)), shellWidgetClass)); /* Pop down the dialog, make pipe fd ready for reading */ XtPopdown(XtParent(XtParent(w))); write(info[fd]->fd, "", 1); /* Get text from XmText widget, then pipe it to mail */ subject = XmTextFieldGetString(info[fd]->subject); dispose(info[fd]->address); info[fd]->address = XmTextFieldGetString(info[fd]->to); sprintf(mailcmd, MAILCMD, subject, info[fd]->address); dispose(subject); debug("mailcmd=%s\n", mailcmd); if (! (f = popen(mailcmd, "w"))) { info[fd]->reply_size = sprintf (info[fd]->reply_document, "Mail command failed:\n%s", mailcmd); } else { text = XmTextGetString(info[fd]->message); fputs(text, f); /* Send it */ dispose(text); (void) pclose(f); info[fd]->reply_size = sprintf (info[fd]->reply_document, "Message has been sent to %s", info[fd]->address); } leave("send_cb\n"); } #line 139 "mailto.c-nw" static void cancel_cb(Widget w, XtPointer client_data, XtPointer call_data) { int fd = (int) client_data; /* Pop down the dialog, make pipe fd ready for reading */ XtPopdown(XtParent(XtParent(w))); write(info[fd]->fd, "", 1); info[fd]->reply_size = sprintf (info[fd]->reply_document, "Message has not been sent."); } #line 164 "mailto.c-nw" static int handle_normal(int fd) { Widget shell, form, to_label, subject_label, send, cancel; /* The popup window */ shell = XtVaCreatePopupShell ("mail-compose", transientShellWidgetClass, W3Atoplevel(), NULL); /* The form inside the popup shell */ form = XtVaCreateManagedWidget ("form", xmFormWidgetClass, shell, XmNmarginHeight, 10, XmNmarginWidth, 10, XmNhorizontalSpacing, 10, XmNverticalSpacing, 10, NULL); /* Children of form */ to_label = XtVaCreateManagedWidget ("to_label", xmLabelGadgetClass, form, XtVaTypedArg, XmNlabelString, XtRString, "To:", 4, XmNtopAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM, NULL); info[fd]->to = XtVaCreateManagedWidget ("to", xmTextFieldWidgetClass, form, XmNvalue, info[fd]->address, XmNtopAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, to_label, XmNrightAttachment, XmATTACH_FORM, NULL); subject_label = XtVaCreateManagedWidget ("subject_label", xmLabelGadgetClass, form, XtVaTypedArg, XmNlabelString, XtRString, "Subject:", 9, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, info[fd]->to, XmNleftAttachment, XmATTACH_FORM, NULL); info[fd]->subject = XtVaCreateManagedWidget ("subject", xmTextFieldWidgetClass, form, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, info[fd]->to, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, subject_label, XmNrightAttachment, XmATTACH_FORM, NULL); send = XtVaCreateManagedWidget ("send", xmPushButtonGadgetClass, form, XtVaTypedArg, XmNlabelString, XtRString, " Send it ", 10, XmNleftAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, NULL); cancel = XtVaCreateManagedWidget ("cancel", xmPushButtonGadgetClass, form, XtVaTypedArg, XmNlabelString, XtRString, " Cancel ", 9, XmNrightAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, NULL); info[fd]->message = XtVaCreateManagedWidget ("message", xmTextWidgetClass, form, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, info[fd]->subject, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, send, XmNeditMode, XmMULTI_LINE_EDIT, NULL); /* Callbacks for the two buttons */ XtAddCallback(send, XmNactivateCallback, send_cb, (XtPointer) fd); XtAddCallback(cancel, XmNactivateCallback, cancel_cb, (XtPointer) fd); /* Pop up the shell window */ XtPopup(shell, XtGrabNonexclusive); /* Return success */ return fd; } #line 248 "mailto.c-nw" static int handle_subscribe(int fd) { info[fd]->reply_size = sprintf (info[fd]->reply_document, "subscribe to mailing list function not implemented yet"); return fd; } static int handle_unsubscribe(int fd) { info[fd]->reply_size = sprintf (info[fd]->reply_document, "unsubscribe from mailing list function not implemented yet"); return fd; } #line 269 "mailto.c-nw" EXPORT Bool initMailTo(char ***protocols, int *nrprotocols) { static char *protos[] = {"mailto"}; *protocols = protos; *nrprotocols = 1; return TRUE; } #line 309 "mailto.c-nw" EXPORT int openMailTo(const char *url, int method, int flags, const char *referer) { char *local_url, *proto, *address, *h; int fd[2]; local_url = newstring(url); proto = tokenize(local_url, ":", &h); if (! proto || ! eq(proto, "mailto")) { errno = EURL; return -1; /* Incorrect URL */ } address = tokenize(h, "", &h); if (! address) { errno = EURL; return -1; /* Missing address */ } if (method != GET_METHOD && method != SUBSCRIBE_METHOD && method != UNSUBSCRIBE_METHOD) { errno = EMETHOD; return -1; /* Incorrect method */ } if (pipe(fd) < 0) { return -1; /* Couldn't open pipe */ } new(info[fd[0]]); info[fd[0]]->address = newstring(address); info[fd[0]]->reply_document[0] = '\0'; info[fd[0]]->reply_offset = 0; info[fd[0]]->reply_size = 0; info[fd[0]]->flags = flags; info[fd[0]]->fd = fd[1]; switch (method) { case GET_METHOD: return handle_normal(fd[0]); case SUBSCRIBE_METHOD: return handle_subscribe(fd[0]); case UNSUBSCRIBE_METHOD: return handle_unsubscribe(fd[0]); } /* NOTREACHED */ } #line 361 "mailto.c-nw" EXPORT Bool infoMailTo(int fd, W3ADocumentInfo *buf) { XtAppContext app_context; /* Check that the argument is valid */ assert(fd > 2 && info[fd] != NULL); /* Check again, in a different way */ assert(info[fd]->reply_size >= 0 && info[fd]->reply_offset >= 0); if (! info[fd]->reply_document[0] && (info[fd]->flags & O_NONBLOCK)) { /* No reply yet, but don't wait for it */ errno = EAGAIN; return FALSE; } else { app_context = XtWidgetToApplicationContext(W3Atoplevel()); while (info[fd]->reply_document[0] == '\0') { /* No reply yet, wait for it */ XtAppProcessEvent(app_context, XtIMAll); } dispose(buf->mime_type); /* Remove current values */ dispose(buf->mime_params); dispose(buf->title); #if REPLY_NONE buf->mime_type = newstring("none"); #else buf->mime_type = newstring("text/html"); #endif buf->title = newstring("Mailer result"); /* Title could be fancier.. */ buf->size = info[fd]->reply_size; return TRUE; } } EXPORT Bool doneMailTo(int fd) { return TRUE; /* Nothing to write */ } #line 409 "mailto.c-nw" EXPORT int peekMailTo(int fd) { /* Check that the argument is valid */ assert(fd > 2 && info[fd] != NULL); /* Check again, in a different way */ assert(info[fd]->reply_size >= 0 && info[fd]->reply_offset >= 0); /* Check that peekMailTo is not called after readMailTo returned 0 */ assert(info[fd]->reply_document[0] == '\0' || info[fd]->reply_size > 0); return info[fd]->reply_document[0] ? 1 : 0; } #line 443 "mailto.c-nw" EXPORT int readMailTo(int fd, char *buf, size_t nbytes) { XtAppContext app_context; int m; /* Check that the argument is valid */ assert(fd > 2 && info[fd] != NULL); /* Check again, in a different way */ assert(info[fd]->reply_size >= 0 && info[fd]->reply_offset >= 0); if (! info[fd]->reply_document[0] && (info[fd]->flags & O_NONBLOCK)) { /* No reply yet, but don't wait for it */ errno = EAGAIN; return -1; } if (! info[fd]->reply_document[0]) { /* No reply yet, wait for it */ app_context = XtWidgetToApplicationContext(W3Atoplevel()); while (info[fd]->reply_document[0] == '\0') XtAppProcessEvent(app_context, XtIMAll); } /* There is a non-empty reply, return the next part of it */ m = min(nbytes, info[fd]->reply_size); strncpy(buf, info[fd]->reply_document + info[fd]->reply_offset, m); info[fd]->reply_offset += m; info[fd]->reply_size -= m; return m; /* 0 means end of doc. */ } #line 478 "mailto.c-nw" EXPORT int writeMailTo(int fd, const char *buf, size_t nbytes) { errno = EMETHOD; return -1; } #line 494 "mailto.c-nw" EXPORT Bool closeMailTo(int fd) { Bool result; assert(fd > 2 && info[fd] != NULL && info[fd]->address != NULL); result = close(fd) >= 0 && close(info[fd]->fd) >= 0; dispose(info[fd]->address); dispose(info[fd]); return result; } #line 509 "mailto.c-nw" EXPORT Bool deleteMailTo(const char *url) { errno = EMETHOD; return FALSE; }