Mercurial > noffle
comparison src/server.c @ 88:1fcdced0246e noffle
[svn] Move posting code to post.c, add command line posting
author | bears |
---|---|
date | Thu, 18 May 2000 13:17:23 +0100 |
parents | dfcb28566d36 |
children | 46062d2f9d20 |
comparison
equal
deleted
inserted
replaced
87:bf8c97460fd7 | 88:1fcdced0246e |
---|---|
1 /* | 1 /* |
2 server.c | 2 server.c |
3 | 3 |
4 $Id: server.c 96 2000-05-17 10:51:22Z enz $ | 4 $Id: server.c 100 2000-05-18 12:17:23Z bears $ |
5 */ | 5 */ |
6 | 6 |
7 #if HAVE_CONFIG_H | 7 #if HAVE_CONFIG_H |
8 #include <config.h> | 8 #include <config.h> |
9 #endif | 9 #endif |
29 #include <unistd.h> | 29 #include <unistd.h> |
30 #include "client.h" | 30 #include "client.h" |
31 #include "common.h" | 31 #include "common.h" |
32 #include "configfile.h" | 32 #include "configfile.h" |
33 #include "content.h" | 33 #include "content.h" |
34 #include "control.h" | |
35 #include "database.h" | 34 #include "database.h" |
36 #include "dynamicstring.h" | 35 #include "dynamicstring.h" |
37 #include "fetch.h" | 36 #include "fetch.h" |
38 #include "fetchlist.h" | 37 #include "fetchlist.h" |
39 #include "group.h" | 38 #include "group.h" |
40 #include "itemlist.h" | 39 #include "itemlist.h" |
41 #include "lock.h" | 40 #include "lock.h" |
42 #include "log.h" | 41 #include "log.h" |
43 #include "online.h" | 42 #include "online.h" |
44 #include "outgoing.h" | |
45 #include "over.h" | 43 #include "over.h" |
46 #include "post.h" | 44 #include "post.h" |
47 #include "protocol.h" | 45 #include "protocol.h" |
48 #include "pseudo.h" | 46 #include "pseudo.h" |
49 #include "request.h" | 47 #include "request.h" |
957 } | 955 } |
958 } | 956 } |
959 return TRUE; | 957 return TRUE; |
960 } | 958 } |
961 | 959 |
962 /* Cancel and return TRUE if need to send cancel message on to server. */ | 960 static Bool |
963 static Bool | 961 doPost( char *arg, const Cmd *cmd ) |
964 controlCancel( const char *cancelId ) | 962 { |
965 { | 963 DynStr *s; |
966 return ( Ctrl_cancel( cancelId ) == CANCEL_NEEDS_MSG ); | 964 Str line; |
967 } | |
968 | |
969 /* | |
970 It's a control message. Currently we only know about 'cancel' | |
971 messages; others are passed on for outside groups, and logged | |
972 as ignored for local groups. | |
973 */ | |
974 static Bool | |
975 handleControl( ItemList *control, ItemList *newsgroups, | |
976 const char *msgId, const DynStr *art ) | |
977 { | |
978 const char *grp; | |
979 const char *op; | |
980 Bool err = FALSE; | |
981 Bool localDone = FALSE; | |
982 | |
983 op = Itl_first( control ); | |
984 if ( op == NULL ) | |
985 { | |
986 Log_err( "Malformed control line." ); | |
987 return TRUE; | |
988 } | |
989 else if ( strcasecmp( op, "cancel" ) == 0 ) | |
990 { | |
991 if ( controlCancel( Itl_next( control ) ) ) | |
992 localDone = TRUE; | |
993 else | |
994 return err; | |
995 } | |
996 | |
997 /* Pass on for outside groups. */ | |
998 for( grp = Itl_first( newsgroups ); | |
999 grp != NULL; | |
1000 grp = Itl_next( newsgroups ) ) | |
1001 { | |
1002 if ( Grp_exists( grp ) && ! Grp_local( grp ) ) | |
1003 { | |
1004 if ( ! Out_add( Grp_server( grp ), msgId, art ) ) | |
1005 { | |
1006 Log_err( "Cannot add posted article to outgoing directory" ); | |
1007 err = TRUE; | |
1008 } | |
1009 break; | |
1010 } | |
1011 } | |
1012 | |
1013 if ( localDone ) | |
1014 return err; | |
1015 | |
1016 /* Log 'can't do' for internal groups. */ | |
1017 for( grp = Itl_first( newsgroups ); | |
1018 grp != NULL; | |
1019 grp = Itl_next( newsgroups ) ) | |
1020 { | |
1021 if ( Grp_exists( grp ) && Grp_local( grp ) ) | |
1022 Log_inf( "Ignoring control '%s' for '%s'.", op, grp ); | |
1023 } | |
1024 | |
1025 return err; | |
1026 } | |
1027 | |
1028 static Bool | |
1029 postArticle( ItemList *newsgroups, const char *msgId, const DynStr *art ) | |
1030 { | |
1031 const char *grp; | |
1032 Bool err; | 965 Bool err; |
1033 Bool oneLocal; | |
1034 | |
1035 err = oneLocal = FALSE; | |
1036 | |
1037 /* Run round first doing all local groups. */ | |
1038 for( grp = Itl_first( newsgroups ); | |
1039 grp != NULL; | |
1040 grp = Itl_next( newsgroups ) ) | |
1041 { | |
1042 if ( Grp_local( grp ) ) | |
1043 { | |
1044 if ( ! oneLocal ) | |
1045 { | |
1046 if ( ! Post_open( DynStr_str( art ) ) ) | |
1047 { | |
1048 err = TRUE; | |
1049 break; | |
1050 } | |
1051 else | |
1052 oneLocal = TRUE; | |
1053 } | |
1054 | |
1055 if ( ! Post_add( grp ) ) | |
1056 err = TRUE; | |
1057 } | |
1058 } | |
1059 if ( oneLocal ) | |
1060 Post_close(); | |
1061 | |
1062 /* Now look for a valid external group. */ | |
1063 for( grp = Itl_first( newsgroups ); | |
1064 grp != NULL; | |
1065 grp = Itl_next( newsgroups ) ) | |
1066 { | |
1067 if ( Grp_exists( grp ) && ! Grp_local( grp ) ) | |
1068 { | |
1069 if ( ! Out_add( Grp_server( grp ), msgId, art ) ) | |
1070 { | |
1071 Log_err( "Cannot add posted article to outgoing directory" ); | |
1072 err = TRUE; | |
1073 } | |
1074 break; | |
1075 } | |
1076 } | |
1077 | |
1078 return err; | |
1079 } | |
1080 | |
1081 static Bool | |
1082 doPost( char *arg, const Cmd *cmd ) | |
1083 { | |
1084 Bool err, replyToFound, dateFound, inHeader; | |
1085 DynStr *s; | |
1086 Str line, field, val, msgId, from; | |
1087 const char* p; | |
1088 ItemList * newsgroups, *control; | |
1089 | 966 |
1090 UNUSED(arg); | 967 UNUSED(arg); |
1091 UNUSED(cmd); | 968 UNUSED(cmd); |
1092 | 969 |
1093 /* | |
1094 Get article and make following changes to the header: | |
1095 - add/replace/cut Message-ID depending on config options | |
1096 - add Reply-To with content of From, if missing | |
1097 (some providers overwrite From field) | |
1098 - rename X-Sender header to X-NOFFLE-X-Sender | |
1099 (some providers want to insert their own X-Sender) | |
1100 | |
1101 For doing this, it is not necessary to parse multiple-line | |
1102 headers. | |
1103 */ | |
1104 putStat( STAT_SEND_ART, "Continue (end with period)" ); | 970 putStat( STAT_SEND_ART, "Continue (end with period)" ); |
1105 fflush( stdout ); | 971 fflush( stdout ); |
1106 Log_dbg( "[S FLUSH]" ); | 972 Log_dbg( "[S FLUSH]" ); |
1107 s = new_DynStr( 10000 ); | 973 s = new_DynStr( 10000 ); |
1108 msgId[ 0 ] = '\0'; | 974 err = FALSE; |
1109 from[ 0 ] = '\0'; | 975 while ( ! err && getTxtLn( line, &err ) ) |
1110 newsgroups = control = NULL; | 976 DynStr_appLn( s, line ); |
1111 replyToFound = dateFound = FALSE; | 977 |
1112 inHeader = TRUE; | 978 if ( ! err |
1113 while ( getTxtLn( line, &err ) ) | 979 && Post_open( DynStr_str( s ) ) |
1114 { | 980 && Post_post( FALSE ) ) |
1115 if ( inHeader ) | |
1116 { | |
1117 p = Utl_stripWhiteSpace( line ); | |
1118 if ( *p == '\0' ) | |
1119 { | |
1120 inHeader = FALSE; | |
1121 if ( from[ 0 ] == '\0' ) | |
1122 Log_err( "Posted message has no From field" ); | |
1123 if ( Cfg_replaceMsgId() ) | |
1124 { | |
1125 Prt_genMsgId( msgId, from, "NOFFLE" ); | |
1126 Log_dbg( "Replacing Message-ID with '%s'", msgId ); | |
1127 } | |
1128 else if ( msgId[ 0 ] == '\0' ) | |
1129 { | |
1130 Prt_genMsgId( msgId, from, "NOFFLE" ); | |
1131 | |
1132 Log_inf( "Adding missing Message-ID '%s'", msgId ); | |
1133 } | |
1134 else if ( ! Prt_isValidMsgId( msgId ) ) | |
1135 { | |
1136 Log_ntc( "Replacing invalid Message-ID with '%s'", | |
1137 msgId ); | |
1138 Prt_genMsgId( msgId, from, "NOFFLE" ); | |
1139 } | |
1140 DynStr_app( s, "Message-ID: " ); | |
1141 DynStr_appLn( s, msgId ); | |
1142 if ( ! replyToFound && from[ 0 ] != '\0' ) | |
1143 { | |
1144 Log_dbg( "Adding Reply-To field to posted message." ); | |
1145 DynStr_app( s, "Reply-To: " ); | |
1146 DynStr_appLn( s, from ); | |
1147 } | |
1148 if ( ! dateFound ) | |
1149 { | |
1150 time_t t; | |
1151 | |
1152 time( &t ); | |
1153 Utl_rfc822Date( t, val ); | |
1154 DynStr_app( s, "Date: " ); | |
1155 DynStr_appLn( s, val ); | |
1156 } | |
1157 DynStr_appLn( s, p ); | |
1158 } | |
1159 else if ( Prt_getField( field, val, p ) ) | |
1160 { | |
1161 if ( strcmp( field, "message-id" ) == 0 ) | |
1162 strcpy( msgId, val ); | |
1163 else if ( strcmp( field, "from" ) == 0 ) | |
1164 { | |
1165 strcpy( from, val ); | |
1166 DynStr_appLn( s, p ); | |
1167 } | |
1168 else if ( strcmp( field, "newsgroups" ) == 0 ) | |
1169 { | |
1170 Utl_toLower( val ); | |
1171 newsgroups = new_Itl ( val, " ," ); | |
1172 DynStr_appLn( s, p ); | |
1173 } | |
1174 else if ( strcmp( field, "control" ) == 0 ) | |
1175 { | |
1176 control = new_Itl ( val, " " ); | |
1177 DynStr_appLn( s, p ); | |
1178 } | |
1179 else if ( strcmp( field, "reply-to" ) == 0 ) | |
1180 { | |
1181 replyToFound = TRUE; | |
1182 DynStr_appLn( s, p ); | |
1183 } | |
1184 else if ( strcmp( field, "date" ) == 0 ) | |
1185 { | |
1186 dateFound = TRUE; | |
1187 DynStr_appLn( s, p ); | |
1188 } | |
1189 else if ( strcmp( field, "x-sender" ) == 0 ) | |
1190 { | |
1191 DynStr_app( s, "X-NOFFLE-X-Sender: " ); | |
1192 DynStr_appLn( s, val ); | |
1193 } | |
1194 else | |
1195 DynStr_appLn( s, p ); | |
1196 } | |
1197 else | |
1198 DynStr_appLn( s, line ); | |
1199 } | |
1200 else | |
1201 DynStr_appLn( s, line ); | |
1202 } | |
1203 if ( inHeader ) | |
1204 Log_err( "Posted message has no body" ); | |
1205 if ( ! err ) | |
1206 { | |
1207 if ( newsgroups == NULL || Itl_count( newsgroups ) == 0 ) | |
1208 { | |
1209 Log_err( "Posted message has no valid Newsgroups header field" ); | |
1210 err = TRUE; | |
1211 } | |
1212 else | |
1213 { | |
1214 const char *grp; | |
1215 Bool knownGrp = FALSE; | |
1216 Bool postAllowedGrp = FALSE; | |
1217 | |
1218 /* Check at least one group is known. */ | |
1219 for( grp = Itl_first( newsgroups ); | |
1220 grp != NULL; | |
1221 grp = Itl_next( newsgroups ) ) | |
1222 { | |
1223 if ( Grp_exists( grp ) ) | |
1224 { | |
1225 knownGrp = TRUE; | |
1226 switch( Grp_postAllow( grp ) ) | |
1227 { | |
1228 case 'n': | |
1229 break; | |
1230 case 'm': | |
1231 /* Can't post to moderated local groups. */ | |
1232 postAllowedGrp = ! Grp_local( grp ); | |
1233 break; | |
1234 default: | |
1235 postAllowedGrp = TRUE; | |
1236 } | |
1237 if ( postAllowedGrp ) | |
1238 break; | |
1239 } | |
1240 } | |
1241 | |
1242 if ( ! knownGrp ) | |
1243 { | |
1244 | |
1245 Log_err( "No known group in Newsgroups header field" ); | |
1246 err = TRUE; | |
1247 } | |
1248 else if ( ! postAllowedGrp ) | |
1249 { | |
1250 | |
1251 Log_err( "No group permits posting" ); | |
1252 err = TRUE; | |
1253 } | |
1254 else | |
1255 { | |
1256 err = ( control == NULL ) | |
1257 ? postArticle( newsgroups, msgId, s ) | |
1258 : handleControl( control, newsgroups, msgId, s ); | |
1259 } | |
1260 } | |
1261 } | |
1262 if ( err ) | |
1263 putStat( STAT_POST_FAILED, "Posting failed" ); | |
1264 else | |
1265 { | 981 { |
1266 putStat( STAT_POST_OK, "Message posted" ); | 982 putStat( STAT_POST_OK, "Message posted" ); |
1267 if ( Online_true() ) | 983 if ( Online_true() ) |
1268 postArts(); | 984 postArts(); |
1269 } | 985 } |
1270 del_Itl( newsgroups ); | 986 else |
1271 del_Itl( control ); | 987 putStat( STAT_POST_FAILED, "Posting failed" ); |
988 Post_close(); | |
1272 del_DynStr( s ); | 989 del_DynStr( s ); |
1273 return TRUE; | 990 return TRUE; |
1274 } | 991 } |
1275 | 992 |
1276 static void | 993 static void |