SERV_OBJS = citserver.ro user_ops.ro support.ro room_ops.ro file_ops.ro \
msgbase.ro config.ro sysdep.ro locate_host.ro housekeeping.ro \
database.ro control.ro logging.ro policy.ro dynloader.ro tools.ro \
- mime_parser.ro html.ro internet_addressing.ro \
+ mime_parser.ro html.ro internet_addressing.ro parsedate.ro \
$(AUTH) $(LIBOBJS:.o=.ro)
citserver: $(SERV_OBJS)
#include "tools.h"
#include "internet_addressing.h"
#include "user_ops.h"
+#include "parsedate.h"
/*
/*
* convert_field() is a helper function for convert_internet_message().
* Given start/end positions for an rfc822 field, it converts it to a Citadel
- * field if it wants to, and unfolds it if necessary
+ * field if it wants to, and unfolds it if necessary.
+ *
+ * Returns 1 if the field was converted and inserted into the Citadel message
+ * structure, implying that the source field should be removed from the
+ * message text.
*/
-void convert_field(struct CtdlMessage *msg, int beg, int end) {
+int convert_field(struct CtdlMessage *msg, int beg, int end) {
char *rfc822;
- char *fieldbuf;
- char field[256];
+ char *key, *value;
int i;
+ int colonpos = (-1);
+ int processed = 0;
+ char buf[256];
+ char *user, *node, *name;
rfc822 = msg->cm_fields['M']; /* M field contains rfc822 text */
- strcpy(field, "");
- for (i = beg; i <= end; ++i) {
- if ((rfc822[i] == ':') && ((i-beg)<sizeof(field))) {
- if (strlen(field)==0) {
- safestrncpy(field, &rfc822[beg], i-beg+1);
- }
- }
+ for (i = end; i >= beg; --i) {
+ if (rfc822[i] == ':') colonpos = i;
+ }
+
+ if (colonpos < 0) return(0); /* no colon? not a valid header line */
+
+ value = mallok((end - beg) + 2);
+ safestrncpy(value, &rfc822[beg], (end-beg)+1);
+ key = value;
+ key[colonpos - beg] = 0;
+ value = &key[(colonpos - beg) + 1];
+ unfold_rfc822_field(value);
+
+ /* Here's the big rfc822-to-citadel loop. */
+
+ if (!strcasecmp(key, "Date")) {
+ lprintf(9, "converting date <%s>\n", value);
+ sprintf(buf, "%ld", parsedate(value) );
+ lprintf(9, "parsed value is <%s>\n", buf);
+ if (msg->cm_fields['T'] != NULL)
+ msg->cm_fields['T'] = strdoop(buf);
+ processed = 1;
+ }
+
+ else if (!strcasecmp(key, "From")) {
+ user = mallok(strlen(value));
+ node = mallok(strlen(value));
+ name = mallok(strlen(value));
+ process_rfc822_addr(value, user, node, name);
+ if (msg->cm_fields['A'] != NULL)
+ msg->cm_fields['A'] = strdoop(user);
+ if (msg->cm_fields['N'] != NULL)
+ msg->cm_fields['N'] = strdoop(node);
+ if (msg->cm_fields['H'] != NULL)
+ msg->cm_fields['H'] = strdoop(name);
+ phree(user);
+ phree(node);
+ phree(name);
+ processed = 1;
}
- fieldbuf = mallok(end - beg + 2);
- safestrncpy(fieldbuf, &rfc822[beg], end-beg+1);
- unfold_rfc822_field(fieldbuf);
- lprintf(9, "Field: key=<%s> value=<%s>\n", field, fieldbuf);
- phree(fieldbuf);
+ else if (!strcasecmp(key, "Subject")) {
+ if (msg->cm_fields['U'] != NULL)
+ msg->cm_fields['U'] = strdoop(key);
+ processed = 1;
+ }
+
+ /* Clean up and move on. */
+ lprintf(9, "Field: key=<%s> value=<%s> processed=%d\n",
+ key, value, processed);
+ phree(key); /* Don't free 'value', it's actually the same buffer */
+ return(processed);
}
int msglen;
int done;
char buf[256];
+ int converted;
msg = mallok(sizeof(struct CtdlMessage));
if (msg == NULL) return msg;
}
/* At this point we have a field. Are we interested in it? */
- convert_field(msg, beg, end);
+ converted = convert_field(msg, beg, end);
+ if (converted) {
+ strcpy(&rfc822[beg], &rfc822[pos]);
+ pos = beg;
+ }
/* If we've hit the end of the message, bail out */
if (pos > strlen(rfc822)) done = 1;
msg->cm_fields['T'] = strdoop(aaa);
}
+ lprintf(9, "checkpoint 1 \n");
/* If this message has no path, we generate one.
*/
+ if (msg->cm_fields['A'] == NULL) {
+ msg->cm_fields['A'] = strdoop("unknown user");
+ }
if (msg->cm_fields['P'] == NULL) {
msg->cm_fields['P'] = strdoop(msg->cm_fields['A']);
for (a=0; a<strlen(msg->cm_fields['P']); ++a) {
strcpy(force_room, force);
+ lprintf(9, "checkpoint 2 \n");
/* Strip non-printable characters out of the recipient name */
strcpy(recipient, rec);
for (a = 0; a < strlen(recipient); ++a)
/* Learn about what's inside, because it's what's inside that counts */
+ lprintf(9, "checkpoint 3 \n");
switch (msg->cm_format_type) {
case 0:
strcpy(content_type, "text/x-citadel-variformat");
}
}
+ lprintf(9, "checkpoint 4 \n");
/* Goto the correct room */
strcpy(hold_rm, CC->quickroom.QRname);
strcpy(actual_rm, CC->quickroom.QRname);
+ lprintf(9, "checkpoint 5 \n");
/* If the user is a twit, move to the twit room for posting */
- if (TWITDETECT) {
+ if ( (CC->logged_in) && (TWITDETECT) ) {
if (CC->usersupp.axlevel == 2) {
strcpy(hold_rm, actual_rm);
strcpy(actual_rm, config.c_twitroom);
}
}
+ lprintf(9, "checkpoint 6 \n");
/* ...or if this message is destined for Aide> then go there. */
if (strlen(force_room) > 0) {
strcpy(actual_rm, force_room);
}
+ lprintf(9, "checkpoint 7 \n");
if (strcasecmp(actual_rm, CC->quickroom.QRname))
getroom(&CC->quickroom, actual_rm);
+ lprintf(9, "checkpoint 8 \n");
/* Perform "before save" hooks (aborting if any return nonzero) */
if (PerformMessageHooks(msg, EVT_BEFORESAVE) > 0) return;
+ lprintf(9, "checkpoint 9 \n");
/* If this message has an Extended ID, perform replication checks */
if (ReplicationChecks(msg) > 0) return;
+ lprintf(9, "checkpoint 10 \n");
/* Network mail - send a copy to the network program. */
if ((strlen(recipient) > 0) && (mailtype != MES_LOCAL)) {
sprintf(aaa, "./network/spoolin/netmail.%04lx.%04x.%04x",
lprintf(2, "ERROR: %s\n", strerror(errno));
}
+ lprintf(9, "checkpoint 11 \n");
/* Save it to disk */
newmsgid = send_message(msg, generate_id, network_fp);
if (network_fp != NULL) {
if (newmsgid <= 0L) return;
+ lprintf(9, "checkpoint 12 \n");
/* Write a supplemental message info record. This doesn't have to
* be a critical section because nobody else knows about this message
* yet.
/* Now figure out where to store the pointers */
+ lprintf(9, "checkpoint 13 \n");
/* If this is being done by the networker delivering a private
* message, we want to BYPASS saving the sender's copy (because there
* is no local sender; it would otherwise go to the Trashcan).
CtdlSaveMsgPointerInRoom(actual_rm, newmsgid, 0);
}
+ lprintf(9, "checkpoint 14 \n");
/* Bump this user's messages posted counter. */
- lgetuser(&CC->usersupp, CC->curr_user);
- CC->usersupp.posted = CC->usersupp.posted + 1;
- lputuser(&CC->usersupp);
+ if (CC->logged_in) {
+ lgetuser(&CC->usersupp, CC->curr_user);
+ CC->usersupp.posted = CC->usersupp.posted + 1;
+ lputuser(&CC->usersupp);
+ }
+ lprintf(9, "checkpoint 15 \n");
/* If this is private, local mail, make a copy in the
* recipient's mailbox and bump the reference count.
*/
}
}
+ lprintf(9, "checkpoint 16 \n");
/* Perform "after save" hooks */
PerformMessageHooks(msg, EVT_AFTERSAVE);
+ lprintf(9, "checkpoint 17 \n");
/* */
if (strcasecmp(hold_rm, CC->quickroom.QRname))
getroom(&CC->quickroom, hold_rm);
#include <sys/types.h>
#include <ctype.h>
#include <time.h>
+#include "parsedate.h"
int date_lex(void);
static void date_error(char *);
-#line 99 "parsedate.y"
+#line 100 "parsedate.y"
typedef union {
time_t Number;
enum _MERIDIAN Meridian;
} YYSTYPE;
-#line 113 "y.tab.c"
+#line 114 "y.tab.c"
#define tDAY 257
#define tDAYZONE 258
#define tMERIDIAN 259
short yyss[YYSTACKSIZE];
YYSTYPE yyvs[YYSTACKSIZE];
#define yystacksize YYSTACKSIZE
-#line 286 "parsedate.y"
+#line 287 "parsedate.y"
/* Month and day table. */
static TABLE MonthDayTable[] = {
/* ARGSUSED */
static void
-date_error(s)
- char *s;
+date_error(char *s)
{
/* NOTREACHED */
}
switch (yyn)
{
case 3:
-#line 117 "parsedate.y"
+#line 118 "parsedate.y"
{
yyHaveTime++;
#ifdef lint
}
break;
case 4:
-#line 126 "parsedate.y"
+#line 127 "parsedate.y"
{
yyHaveTime++;
yyTimezone = yyvsp[0].Number;
}
break;
case 5:
-#line 130 "parsedate.y"
+#line 131 "parsedate.y"
{
yyHaveDate++;
}
break;
case 6:
-#line 133 "parsedate.y"
+#line 134 "parsedate.y"
{
yyHaveRel = 1;
}
break;
case 7:
-#line 138 "parsedate.y"
+#line 139 "parsedate.y"
{
if (yyvsp[-1].Number < 100) {
yyHour = yyvsp[-1].Number;
}
break;
case 8:
-#line 150 "parsedate.y"
+#line 151 "parsedate.y"
{
yyHour = yyvsp[-3].Number;
yyMinutes = yyvsp[-1].Number;
}
break;
case 9:
-#line 156 "parsedate.y"
+#line 157 "parsedate.y"
{
yyHour = yyvsp[-3].Number;
yyMinutes = yyvsp[-1].Number;
}
break;
case 10:
-#line 163 "parsedate.y"
+#line 164 "parsedate.y"
{
yyHour = yyvsp[-5].Number;
yyMinutes = yyvsp[-3].Number;
}
break;
case 11:
-#line 169 "parsedate.y"
+#line 170 "parsedate.y"
{
yyHour = yyvsp[-5].Number;
yyMinutes = yyvsp[-3].Number;
}
break;
case 12:
-#line 179 "parsedate.y"
+#line 180 "parsedate.y"
{
yyval.Number = yyvsp[0].Number;
yyDSTmode = DSToff;
}
break;
case 13:
-#line 183 "parsedate.y"
+#line 184 "parsedate.y"
{
yyval.Number = yyvsp[0].Number;
yyDSTmode = DSTon;
}
break;
case 14:
-#line 187 "parsedate.y"
+#line 188 "parsedate.y"
{
/* Only allow "GMT+300" and "GMT-0800" */
if (yyvsp[-1].Number != 0) {
}
break;
case 15:
-#line 195 "parsedate.y"
+#line 196 "parsedate.y"
{
yyval.Number = yyvsp[0].Number;
yyDSTmode = DSToff;
}
break;
case 16:
-#line 201 "parsedate.y"
+#line 202 "parsedate.y"
{
int i;
}
break;
case 17:
-#line 222 "parsedate.y"
+#line 223 "parsedate.y"
{
yyMonth = yyvsp[-2].Number;
yyDay = yyvsp[0].Number;
}
break;
case 18:
-#line 226 "parsedate.y"
+#line 227 "parsedate.y"
{
if (yyvsp[-4].Number > 100) {
yyYear = yyvsp[-4].Number;
}
break;
case 19:
-#line 238 "parsedate.y"
+#line 239 "parsedate.y"
{
yyMonth = yyvsp[-1].Number;
yyDay = yyvsp[0].Number;
}
break;
case 20:
-#line 242 "parsedate.y"
+#line 243 "parsedate.y"
{
yyMonth = yyvsp[-3].Number;
yyDay = yyvsp[-2].Number;
}
break;
case 21:
-#line 247 "parsedate.y"
+#line 248 "parsedate.y"
{
yyDay = yyvsp[-1].Number;
yyMonth = yyvsp[0].Number;
}
break;
case 22:
-#line 251 "parsedate.y"
+#line 252 "parsedate.y"
{
yyDay = yyvsp[-2].Number;
yyMonth = yyvsp[-1].Number;
}
break;
case 23:
-#line 256 "parsedate.y"
+#line 257 "parsedate.y"
{
yyDay = yyvsp[-2].Number;
yyMonth = yyvsp[-1].Number;
}
break;
case 24:
-#line 263 "parsedate.y"
+#line 264 "parsedate.y"
{
yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
}
break;
case 25:
-#line 266 "parsedate.y"
+#line 267 "parsedate.y"
{
yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
}
break;
case 26:
-#line 269 "parsedate.y"
+#line 270 "parsedate.y"
{
yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
}
break;
case 27:
-#line 272 "parsedate.y"
+#line 273 "parsedate.y"
{
yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
}
break;
case 28:
-#line 277 "parsedate.y"
+#line 278 "parsedate.y"
{
yyval.Meridian = MER24;
}
break;
case 29:
-#line 280 "parsedate.y"
+#line 281 "parsedate.y"
{
yyval.Meridian = yyvsp[0].Meridian;
}
--- /dev/null
+time_t parsedate(char *);
#include <sys/types.h>
#include <ctype.h>
#include <time.h>
+#include "parsedate.h"
int date_lex(void);
/* ARGSUSED */
static void
-date_error(s)
- char *s;
+date_error(char *s)
{
/* NOTREACHED */
}
fprintf(stderr, "Converting message...\n");
msg = convert_internet_message(body);
-
phree(body);
- cprintf("599 command unfinished\n");
+
+ CtdlSaveMsg(msg, "", BASEROOM, MES_LOCAL, 1); /* FIX temporary */
+ CtdlFreeMessage(msg);
+
+ cprintf("599 command unfinished but message saved\n");
}