]> code.citadel.org Git - citadel.git/blobdiff - citadel/modules/nntp/serv_nntp.c
Set up per-session NNTP state structure, alloc and free
[citadel.git] / citadel / modules / nntp / serv_nntp.c
index 6f6f41fa706f67317ea56006793bccf541860713..1978c269ad85146ec9289551ecfe7b6dde4fa51d 100644 (file)
@@ -185,9 +185,9 @@ void nntp_greeting(void)
        strcpy(CC->cs_clientname, "NNTP session");
        CC->cs_flags |= CS_STEALTH;
 
-       /* CC->session_specific_data = malloc(sizeof(citnntp));
-       memset(NNTP, 0, sizeof(citnntp));
-       */
+       CC->session_specific_data = malloc(sizeof(citnntp));
+       citnntp *nntpstate = (citnntp *) CC->session_specific_data;
+       memset(nntpstate, 0, sizeof(citnntp));
 
        if (CC->nologin==1) {
                cprintf("451 Too many connections are already open; please try again later.\r\n");
@@ -718,6 +718,12 @@ void nntp_article(const char *cmd) {
                return;
        }
 
+       // Which NNTP command was issued, determines whether we will fetch headers, body, or both.
+       int                     headers_only = HEADERS_ALL;
+       if (acmd == HEAD)       headers_only = HEADERS_FAST;
+       else if (acmd == BODY)  headers_only = HEADERS_NONE;
+       else if (acmd == STAT)  headers_only = HEADERS_FAST;
+
        // now figure out what the client is asking for.
        char requested_article[256];
        long requested_msgnum = 0;
@@ -747,15 +753,55 @@ void nntp_article(const char *cmd) {
        }
 
        // Anything else is noncompliant gobbledygook and should die in a car fire.
+       // Also, the weasel who is spreading untrue rumors about me at work should die in a slow and painful car fire.
        else {
                cprintf("500 syntax error\r\n");
                return;
        }
 
+       // At this point we know the message number of the "article" being requested.
+       // We have an awesome API call that does all the heavy lifting for us.
+       char *fetched_message_id = NULL;
+       CC->redirect_buffer = NewStrBufPlain(NULL, SIZ);
+       int fetch = CtdlOutputMsg(requested_msgnum,
+                       MT_RFC822,              // output in RFC822 format ... sort of
+                       headers_only,           // headers, body, or both?
+                       0,                      // don't do Citadel protocol responses
+                       1,                      // CRLF newlines
+                       NULL,                   // teh whole thing, not just a section
+                       0,                      // no flags yet ... maybe new ones for Path: etc ?
+                       NULL,
+                       NULL,
+                       &fetched_message_id     // extract the message ID from the message as we go...
+       );
+       StrBuf *msgtext = CC->redirect_buffer;
+       CC->redirect_buffer = NULL;
+
+       if (fetch != om_ok) {
+               cprintf("423 no article with that number\r\n");
+               FreeStrBuf(&msgtext);
+               return;
+       }
 
+       if (acmd == ARTICLE) {
+               cprintf("220 %ld <%s>\r\n", requested_msgnum, fetched_message_id);
+       }
+       if (acmd == HEAD) {
+               cprintf("221 %ld <%s>\r\n", requested_msgnum, fetched_message_id);
+       }
+       if (acmd == BODY) {
+               cprintf("222 %ld <%s>\r\n", requested_msgnum, fetched_message_id);
+       }
+       if (acmd == STAT) {
+               cprintf("223 %ld <%s>\r\n", requested_msgnum, fetched_message_id);
+               FreeStrBuf(&msgtext);
+               return;
+       }
 
-
-       cprintf("500 FIXME write the rest of cmd=%d msgnum=%ld\r\n", acmd, requested_msgnum);
+       client_write(SKEY(msgtext));
+       cprintf(".\r\n");                       // this protocol uses a dot terminator
+       FreeStrBuf(&msgtext);
+       if (fetched_message_id) free(fetched_message_id);
 }
 
 
@@ -851,6 +897,11 @@ void nntp_cleanup_function(void)
        if (CC->h_command_function != nntp_command_loop) return;
 
        syslog(LOG_DEBUG, "Performing NNTP cleanup hook\n");
+       citnntp *nntpstate = (citnntp *) CC->session_specific_data;
+       if (nntpstate != NULL) {
+               free(nntpstate);
+               nntpstate = NULL;
+       }
 }
 
 const char *CitadelServiceNNTP="NNTP";