This is post.c in view mode; [Download] [Up]
/* Copyright (c) 1995 John E. Davis (davis@space.mit.edu)
* All rights reserved.
*/
/* post an article */
#include "config.h"
#include "features.h"
#include <stdio.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#include <sys/types.h>
#include <time.h>
#include <slang.h>
#include "jdmacros.h"
/* #include "clientlib.h" */
#include "slrn.h"
#include "server.h"
#include "misc.h"
#include "post.h"
#include "group.h"
#include "art.h"
#include "uudecode.h"
#if SLRN_HAS_MIME
# include "mime.h"
#endif
char *Slrn_Courtesy_CC_Message = NULL;
char *Slrn_Save_Posts_File;
char *Slrn_Last_Message_Id;
char *Slrn_Custom_Headers;
#ifdef VMS
# define SYSTEM_OS_NAME "VMS"
#else
# ifdef __os2__
# define SYSTEM_OS_NAME "OS2"
# else
# ifdef unix
# define SYSTEM_OS_NAME "UNIX"
# else
# define SYSTEM_OS_NAME "UNKNOWN"
# endif
# endif
#endif
#define SLRN_GEN_MSGID
#ifdef SLRN_GEN_MSGID
static char *slrn_create_message_id (void)
{
unsigned long pid, now;
static unsigned char baseid[64];
unsigned char *b, *t, tmp[32];
char *chars32 = "0123456789abcdefghijklmnopqrstuv";
static unsigned long last_now;
while (1)
{
if ((Slrn_User_Info.posting_host == NULL)
|| ((time_t) -1 == time ((time_t *)&now)))
return NULL;
if (now != last_now) break;
sleep (1);
}
last_now = now;
pid = (unsigned long) getpid ();
now -= 0x28000000;
b = baseid;
t = tmp;
while (now)
{
*t++ = chars32[now & 0x1F];
now = now >> 5;
}
while (t > tmp)
{
t--;
*b++ = *t;
}
*b++ = '.';
t = tmp;
while (pid)
{
*t++ = chars32[pid & 0x1F];
pid = pid >> 5;
}
while (t > tmp)
{
t--;
*b++ = *t;
}
*b++ = '.';
t = (unsigned char *) Slrn_User_Info.username;
if (t != NULL)
while ((*t != 0) && (b < baseid + sizeof(baseid) - 1)) *b++ = *t++;
*b = 0;
return (char *) baseid;
}
#endif
void slrn_add_signature (FILE *fp)
{
FILE *sfp;
char buf[256];
if ((sfp = slrn_open_home_file (Slrn_User_Info.signature, "r", buf, 0)) != NULL)
{
/* Apparantly some RFC suggests the -- \n. */
fprintf(fp, "\n\n-- \n");
while (fgets (buf, sizeof(buf) - 1, sfp) != NULL)
{
fprintf(fp, "%s", buf);
}
slrn_fclose(sfp);
}
}
static int is_empty_header (char *line)
{
char *b;
if ((*line == ' ') || (*line == '\t')) return 0;
b = slrn_strchr (line, ':');
if (b == NULL) return 0;
b = slrn_skip_whitespace (b + 1);
return (*b == 0);
}
static int slrn_cc_file (char *file, char *to)
{
#if defined(VMS) || !SLRN_HAS_PIPING
return -1;
#else
FILE *pp, *fp;
char line[1024];
unsigned char *b;
unsigned int cc_line = 0;
unsigned int linenum;
int num_ccd;
if (NULL == (fp = fopen (file, "r")))
{
slrn_error ("Unable to open %s.");
return -1;
}
/* Look for CC line */
linenum = 0;
while ((NULL != fgets (line, sizeof (line) - 1, fp)) && (*line != '\n'))
{
linenum++;
if (0 == slrn_case_strncmp ((unsigned char *)line,
(unsigned char *) "Cc: ", 4))
{
b = (unsigned char *) slrn_skip_whitespace (line + 4);
if (*b && (*b != ',')) cc_line = linenum;
break;
}
}
/* At this point, if all has gone well line contains the cc information */
if (cc_line == 0)
{
slrn_fclose (fp);
return -1;
}
pp = slrn_popen (Slrn_SendMail_Command, "w");
if (pp == NULL)
{
slrn_fclose (fp);
return -1;
}
fputs ("To: ", pp);
num_ccd = 0;
b = (unsigned char *) line + 4;
while (*b != 0)
{
unsigned char *bmin, ch;
/* skip to first non-whitespace, non-comma char */
if ((*b <= ' ') || (*b == ','))
{
b++;
continue;
}
bmin = b;
/* Now skip past to white space or comma */
while (((ch = *b) != ',') && (ch > ' ')) b++;
if ((b == bmin + 6)
&& (0 == slrn_case_strncmp (bmin, (unsigned char *) "poster", 6)))
{
if (to != NULL)
{
if (num_ccd) putc (',', pp);
fputs (to, pp);
num_ccd++;
to = NULL;
}
}
else
{
if (num_ccd) putc (',', pp);
fwrite ((char *)bmin, 1, (unsigned int) (b - bmin), pp);
num_ccd++;
}
}
putc ('\n', pp);
rewind (fp);
linenum = 0;
while ((NULL != fgets (line, sizeof (line) - 1, fp)) && (*line != '\n'))
{
linenum++;
if (linenum == cc_line) continue;
if (is_empty_header (line)) continue;
if (0 == slrn_case_strncmp ((unsigned char *)line,
(unsigned char *) "To: ", 4))
continue;
/* There is some discussion of this extension to mail headers. For
* now, assume that this extension will be adopted.
*/
if (0 == slrn_case_strncmp ((unsigned char *)line,
(unsigned char *) "Newsgroups: ", 12))
{
fputs ("Posted-To: ", pp);
fputs (line + 12, pp);
}
else
fputs (line, pp);
}
# if SLRN_HAS_MIME
if (Slrn_Use_Mime) slrn_mime_add_headers (pp);
# endif
fputs ("\n", pp);
if ((NULL != Slrn_Courtesy_CC_Message) && (*Slrn_Courtesy_CC_Message))
fprintf (pp, "%s\n", Slrn_Courtesy_CC_Message);
# if SLRN_HAS_MIME
if (Slrn_Use_Mime) fp = slrn_mime_encode (fp);
# endif
while (NULL != fgets (line, sizeof (line) - 1, fp))
{
fputs (line, pp);
}
slrn_fclose (fp);
slrn_pclose (pp);
return 0;
#endif
}
/* This function needs work-- in fact, I ought to move this to a separate
* file for this purpose.
*/
static int check_file_for_posting (char *file)
{
char line[1024], *the_line;
FILE *fp;
unsigned int num;
char *err;
int rsp;
int newsgroups_found, subject_found;
char ch;
char *colon;
try_again:
newsgroups_found = subject_found = 0;
err = NULL;
fp = fopen (file, "r");
if (fp == NULL)
{
slrn_error ("Unable to open %s", file);
return -1;
}
the_line = line;
/* scan the header */
num = 0;
while (NULL != fgets (line, sizeof (line), fp))
{
ch = *line;
num++;
if ((ch == ' ') || (ch == '\t') || (ch == '\n'))
{
if (num == 1)
{
err = "The first line must begin with a header.";
break;
}
if (ch == '\n') break;
continue;
}
if (NULL == (colon = slrn_strchr (line, ':')))
{
err = "Expecting a header. This is not a header line.";
break;
}
if (!slrn_case_strncmp ((unsigned char *) line, (unsigned char *) "Subject:", 8))
{
if (is_empty_header (line))
{
err = "The subject header is not allowed be to empty.";
break;
}
subject_found = 1;
continue;
}
if (!slrn_case_strncmp ((unsigned char *) line, (unsigned char *) "Newsgroups:", 11))
{
if (is_empty_header (line))
{
err = "The Newsgroups header is not allowed be to empty.";
break;
}
newsgroups_found = 1;
continue;
}
/* slrn will remove it later if it is empty */
if (is_empty_header (line)) continue;
if (*(colon + 1) != ' ')
{
err = "A space must follow the ':' in a header";
break;
}
if (!slrn_case_strncmp ((unsigned char *) line, (unsigned char *) "From:", 5))
{
err = "This news reader will not accept user generated From lines.";
break;
}
}
if (err == NULL)
{
if (subject_found == 0)
{
err = "Subject header is required.";
num = 0;
}
else if (newsgroups_found == 0)
{
err = "Newsgroups header is required.";
num = 0;
}
}
/* Now body. Check for non-quoted lines. */
if (err == NULL)
{
unsigned int qlen = strlen (Slrn_Quote_String);
err = "Your message does not appear to have any unquoted text.";
while (NULL != fgets (line, sizeof (line), fp))
{
num++;
if (!strncmp (line, Slrn_Quote_String, qlen))
continue;
colon = slrn_skip_whitespace (line);
if (*colon == 0) continue;
err = NULL;
break;
}
the_line = NULL;
}
fclose (fp);
if (err == NULL) return 0;
Slrn_Full_Screen_Update = 1;
slrn_set_color (0);
SLsmg_cls ();
SLsmg_gotorc (2,0);
slrn_set_color (SUBJECT_COLOR);
SLsmg_write_string ("Your message is not acceptable for the following reason:");
slrn_set_color (ERROR_COLOR);
SLsmg_gotorc (4,8); SLsmg_write_string (err);
if (num && (the_line != NULL))
{
SLsmg_gotorc (6,0);
slrn_set_color (SUBJECT_COLOR);
SLsmg_printf ("This message was generated while looking at line %d:", num);
SLsmg_gotorc (8,0);
slrn_set_color (QUOTE_COLOR);
SLsmg_printf (the_line);
SLsmg_gotorc (12, 0);
slrn_set_color (ARTICLE_COLOR);
SLsmg_write_string ("Perhaps this error was generated because you did not separate the header");
SLsmg_gotorc (13, 0);
SLsmg_write_string ("section from the body by a BLANK line.");
}
rsp = slrn_get_response ("yYnNcC\007", "Press 'Y' to re-edit or 'C' to cancel");
rsp |= 0x20;
if (rsp == 'y')
{
if (slrn_edit_file (file, num) < 0) return -1;
goto try_again;
}
return -1;
}
int slrn_post_file (char *file, char *to)
{
char line[1024], *linep;
int len, header;
FILE *fp;
int rsp;
int perform_cc;
#ifdef SLRN_GEN_MSGID
char *msgid;
int has_messageid = 0;
#endif
try_again:
perform_cc = 0;
while (1)
{
rsp = slrn_get_response ("yYnNeE", "Post the message? Y-es, N-o, E-dit");
rsp |= 0x20;
if (rsp == 'n') return -1;
if (rsp == 'y') break;
if (slrn_edit_file (file, 1) < 0)
{
slrn_error ("User abort.");
return -1;
}
}
if (-1 == check_file_for_posting (file)) return -1;
slrn_message ("Posting..."); slrn_smg_refresh ();
if ((Slrn_Save_Posts_File != NULL) && (*Slrn_Save_Posts_File))
{
FILE *infp, *outfp;
time_t now;
char save_post_file[256];
if (NULL == (infp = fopen (file, "r")))
{
slrn_error ("File not found: %s--- message not posted.", file);
return -1;
}
if (NULL == (outfp = slrn_open_home_file (Slrn_Save_Posts_File, "at",
save_post_file, 1)))
{
slrn_error ("Error saving to %s", save_post_file);
slrn_fclose (infp);
return -1;
}
time (&now);
fprintf (outfp, "From %s@%s %s", Slrn_User_Info.username, Slrn_User_Info.host, ctime(&now));
fprintf (outfp, "From: %s@%s (%s)\n", Slrn_User_Info.username, Slrn_User_Info.host, Slrn_User_Info.realname);
while (fgets (line, sizeof(line) - 1, infp) != NULL)
{
if ((*line == 'F')
&& !strncmp ("From", line, 4)
&& ((unsigned char)line[4] <= ' '))
{
putc ('>', outfp);
}
fputs (line, outfp);
}
fputs ("\n\n", outfp);
slrn_fclose (infp);
slrn_fclose (outfp);
}
if ((fp = fopen (file, "r")) == NULL)
{
slrn_error ("File not found: %s--- message not posted.", file);
return -1;
}
#if SLRN_HAS_MIME
if (Slrn_Use_Mime)
slrn_mime_scan_file (fp);
#endif
if (Slrn_Post_Obj->po_start () < 0) return -1;
if (Slrn_User_Info.username != NULL)
Slrn_Post_Obj->po_printf ("Path: %s\r\n", Slrn_User_Info.username);
Slrn_Post_Obj->po_printf ("From: %s@%s (%s)\r\n", Slrn_User_Info.username, Slrn_User_Info.host, Slrn_User_Info.realname);
/* if (Slrn_User_Info.posting_host != NULL)
* Slrn_Post_Obj->po_printf ("X-Posting-Host: %s\r\n", Slrn_User_Info.posting_host); */
linep = line + 1;
header = 1;
while (fgets (linep, sizeof(line) - 1, fp) != NULL)
{
len = strlen (linep);
if (len == 0) continue;
if (header)
{
unsigned char *b;
char *white = linep;
while ((*white == ' ') || (*white == '\t')) white++;
if (*white == '\n')
{
#ifdef SLRN_GEN_MSGID
if (has_messageid == 0)
{
Slrn_Last_Message_Id = msgid = slrn_create_message_id ();
if (msgid != NULL)
{
Slrn_Post_Obj->po_printf ("Message-Id: <slrn%s@%s>\r\n", msgid, Slrn_User_Info.posting_host);
}
}
#endif
#if SLRN_HAS_MIME
if (Slrn_Use_Mime)
slrn_mime_add_headers (0); /* 0 --> Slrn_Post_Obj->po_puts */
#endif
Slrn_Post_Obj->po_printf ("X-Newsreader: slrn (%s %s)\r\n\r\n", Slrn_Version,
SYSTEM_OS_NAME);
header = 0;
#if SLRN_HAS_MIME
if (Slrn_Use_Mime) fp = slrn_mime_encode (fp);
#endif
continue;
}
if (!slrn_case_strncmp ((unsigned char *)"Cc: ",
(unsigned char *)linep, 4))
{
b = (unsigned char *) linep + 4;
b = (unsigned char *) slrn_skip_whitespace ((char *) b);
if (*b && (*b != ',')) perform_cc = 1;
continue;
}
if (is_empty_header (linep)) continue;
#ifdef SLRN_GEN_MSGID
if (!slrn_case_strncmp ((unsigned char *)"Message-Id: ",
(unsigned char *)linep, 12))
has_messageid = 1;
#endif
linep[len - 1] = 0;
#if SLRN_HAS_MIME
if (Slrn_Use_Mime)
slrn_mime_header_encode (linep, sizeof (line) - 1);
#endif
}
if (linep[len - 1] == '\n')
{
len--;
linep[len] = 0;
}
if (*linep == '.')
{
linep--;
*linep = '.';
}
Slrn_Post_Obj->po_puts (linep);
Slrn_Post_Obj->po_puts ("\r\n");
linep = line + 1;
}
slrn_fclose (fp);
if (Slrn_Post_Obj->po_end () == 0) slrn_message ("Posting...done.");
else
{
slrn_smg_refresh ();
sleep (2);
slrn_clear_message (); SLang_Error = 0;
rsp = slrn_get_response ("RrEeCc", "Select one: R-epost, E-dit, C-ancel");
rsp |= 0x20;
if (rsp == 'c') return -1;
if ((rsp == 'e') && (slrn_edit_file (file, 1) < 0)) return -1;
goto try_again;
}
if (perform_cc)
{
slrn_cc_file (file, to);
}
return 0;
}
int slrn_post (char *newsgroup, char *subj, char *dist)
{
FILE *fp;
char file[256];
unsigned int header_lines;
int ret;
if (Slrn_Use_Tmpdir)
{
fp = slrn_open_tmpfile (file, "w");
}
else fp = slrn_open_home_file (SLRN_ARTICLE_FILENAME, "w", file, 0);
if (fp == NULL)
{
slrn_error ("Unable to create %s.", file);
return -1;
}
header_lines = 9;
fprintf (fp, "Newsgroups: %s\nSubject: %s\n", newsgroup, subj);
if (Slrn_User_Info.org != NULL)
{
header_lines++;
fprintf (fp, "Organization: %s\n", Slrn_User_Info.org);
}
fprintf (fp, "Reply-To: %s\nFollowup-To: \n", Slrn_User_Info.replyto);
fprintf (fp, "Keywords: \nSummary: \n");
if (dist != NULL) fprintf (fp, "Distribution: %s\n", dist);
header_lines += slrn_add_custom_headers (fp);
fputs ("\n", fp);
slrn_add_signature (fp);
slrn_fclose (fp);
if (slrn_edit_file (file, header_lines) >= 0)
{
ret = slrn_post_file (file, NULL);
}
else ret = -1;
if (Slrn_Use_Tmpdir) (void) slrn_delete_file (file);
return ret;
}
int slrn_add_custom_headers (FILE *fp)
{
int n;
char *s, *s1, ch, last_ch;
if (Slrn_Custom_Headers == NULL) return 0;
s = slrn_skip_whitespace (Slrn_Custom_Headers);
if (*s == 0) return 0;
s1 = s;
n = 0;
last_ch = 0;
while ((ch = *s1) != 0)
{
if (ch == '\n') n++;
last_ch = ch;
s1++;
}
fputs (s, fp);
if (last_ch != '\n')
{
fputs ("\n", fp);
n++;
}
return n;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.