Imported Upstream version 8.16
Michael Meskes
11 years ago
3 | 3 | * The condensed version: |
4 | 4 | |
5 | 5 | 1. Create a user on your system under which to run Citadel |
6 | 2. Install supported versions of Berkeley DB, libical, and libsieve. | |
6 | 2. Install supported versions of all dependencies | |
7 | 7 | 3. ./configure && make && make install |
8 | 8 | 4. Run the "setup" program |
9 | 9 |
0 | 0 | /* |
1 | 1 | * Main Citadel header file |
2 | 2 | * |
3 | * Copyright (c) 1987-2012 by the citadel.org team | |
3 | * Copyright (c) 1987-2013 by the citadel.org team | |
4 | 4 | * |
5 | 5 | * This program is open source software; you can redistribute it and/or modify |
6 | 6 | * it under the terms of the GNU General Public License version 3. |
44 | 44 | * usually more strict because you're not really supposed to dump/load and |
45 | 45 | * upgrade at the same time. |
46 | 46 | */ |
47 | #define REV_LEVEL 814 /* This version */ | |
47 | #define REV_LEVEL 816 /* This version */ | |
48 | 48 | #define REV_MIN 591 /* Oldest compatible database */ |
49 | 49 | #define EXPORT_REV_MIN 760 /* Oldest compatible export files */ |
50 | #define LIBCITADEL_MIN 814 /* Minimum required version of libcitadel */ | |
50 | #define LIBCITADEL_MIN 816 /* Minimum required version of libcitadel */ | |
51 | 51 | |
52 | 52 | #define SERVER_TYPE 0 /* zero for stock Citadel; other developers please |
53 | 53 | obtain SERVER_TYPE codes for your implementations */ |
283 | 283 | cprintf("0\n"); /* 1 = no, this server is not LDAP-enabled */ |
284 | 284 | #endif |
285 | 285 | |
286 | if (config.c_auth_mode == AUTHMODE_NATIVE) { | |
286 | if ((config.c_auth_mode == AUTHMODE_NATIVE) && | |
287 | (config.c_disable_newu == 0)) | |
288 | { | |
287 | 289 | cprintf("%d\n", config.c_disable_newu); |
288 | 290 | } |
289 | 291 | else { |
0 | 0 | #! /bin/sh |
1 | 1 | # From configure.ac Revision: 5108 . |
2 | 2 | # Guess values for system-dependent variables and create Makefiles. |
3 | # Generated by GNU Autoconf 2.67 for Citadel 8.14. | |
3 | # Generated by GNU Autoconf 2.67 for Citadel 8.16. | |
4 | 4 | # |
5 | 5 | # Report bugs to <http://www.citadel.org/>. |
6 | 6 | # |
552 | 552 | # Identity of this package. |
553 | 553 | PACKAGE_NAME='Citadel' |
554 | 554 | PACKAGE_TARNAME='citadel' |
555 | PACKAGE_VERSION='8.14' | |
556 | PACKAGE_STRING='Citadel 8.14' | |
555 | PACKAGE_VERSION='8.16' | |
556 | PACKAGE_STRING='Citadel 8.16' | |
557 | 557 | PACKAGE_BUGREPORT='http://www.citadel.org/' |
558 | 558 | PACKAGE_URL='' |
559 | 559 | |
1264 | 1264 | # Omit some internal or obsolete options to make the list less imposing. |
1265 | 1265 | # This message is too long to be a string in the A/UX 3.1 sh. |
1266 | 1266 | cat <<_ACEOF |
1267 | \`configure' configures Citadel 8.14 to adapt to many kinds of systems. | |
1267 | \`configure' configures Citadel 8.16 to adapt to many kinds of systems. | |
1268 | 1268 | |
1269 | 1269 | Usage: $0 [OPTION]... [VAR=VALUE]... |
1270 | 1270 | |
1329 | 1329 | |
1330 | 1330 | if test -n "$ac_init_help"; then |
1331 | 1331 | case $ac_init_help in |
1332 | short | recursive ) echo "Configuration of Citadel 8.14:";; | |
1332 | short | recursive ) echo "Configuration of Citadel 8.16:";; | |
1333 | 1333 | esac |
1334 | 1334 | cat <<\_ACEOF |
1335 | 1335 | |
1447 | 1447 | test -n "$ac_init_help" && exit $ac_status |
1448 | 1448 | if $ac_init_version; then |
1449 | 1449 | cat <<\_ACEOF |
1450 | Citadel configure 8.14 | |
1450 | Citadel configure 8.16 | |
1451 | 1451 | generated by GNU Autoconf 2.67 |
1452 | 1452 | |
1453 | 1453 | Copyright (C) 2010 Free Software Foundation, Inc. |
2105 | 2105 | This file contains any messages produced by compilers while |
2106 | 2106 | running configure, to aid debugging if configure makes a mistake. |
2107 | 2107 | |
2108 | It was created by Citadel $as_me 8.14, which was | |
2108 | It was created by Citadel $as_me 8.16, which was | |
2109 | 2109 | generated by GNU Autoconf 2.67. Invocation command line was |
2110 | 2110 | |
2111 | 2111 | $ $0 $@ |
8456 | 8456 | # report actual input values of CONFIG_FILES etc. instead of their |
8457 | 8457 | # values after options handling. |
8458 | 8458 | ac_log=" |
8459 | This file was extended by Citadel $as_me 8.14, which was | |
8459 | This file was extended by Citadel $as_me 8.16, which was | |
8460 | 8460 | generated by GNU Autoconf 2.67. Invocation command line was |
8461 | 8461 | |
8462 | 8462 | CONFIG_FILES = $CONFIG_FILES |
8518 | 8518 | cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 |
8519 | 8519 | ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" |
8520 | 8520 | ac_cs_version="\\ |
8521 | Citadel config.status 8.14 | |
8521 | Citadel config.status 8.16 | |
8522 | 8522 | configured by $0, generated by GNU Autoconf 2.67, |
8523 | 8523 | with options \\"\$ac_cs_config\\" |
8524 | 8524 |
0 | 0 | dnl Process this file with autoconf to produce a configure script. |
1 | 1 | AC_PREREQ(2.52) |
2 | AC_INIT([Citadel], [8.14], [http://www.citadel.org/]) | |
2 | AC_INIT([Citadel], [8.16], [http://www.citadel.org/]) | |
3 | 3 | AC_REVISION([$Revision: 5108 $]) |
4 | 4 | AC_CONFIG_SRCDIR([citserver.c]) |
5 | 5 | AC_CONFIG_HEADER(sysdep.h) |
88 | 88 | { |
89 | 89 | if (!IsEmptyStr(msg)) { |
90 | 90 | syslog(LOG_DEBUG, "DB: %s", msg); |
91 | cit_backtrace(); | |
91 | 92 | } |
92 | 93 | } |
93 | 94 | |
96 | 97 | void cdb_verbose_err(const DB_ENV *dbenv, const char *errpfx, const char *msg) |
97 | 98 | { |
98 | 99 | syslog(LOG_ALERT, "DB: %s", msg); |
100 | cit_backtrace(); | |
99 | 101 | } |
100 | 102 | |
101 | 103 | |
141 | 143 | static void dbpanic(DB_ENV * env, int errval) |
142 | 144 | { |
143 | 145 | syslog(LOG_EMERG, "bdb(): PANIC: %s", db_strerror(errval)); |
146 | cit_backtrace(); | |
144 | 147 | } |
145 | 148 | |
146 | 149 | static void cclose(DBC * cursor) |
368 | 368 | case eSendMore: |
369 | 369 | assert(IO->SendDone); |
370 | 370 | IO->NextState = IO->SendDone(IO); |
371 | ev_io_start(event_base, &IO->send_event); | |
371 | switch (IO->NextState) | |
372 | { | |
373 | case eSendFile: | |
374 | case eSendReply: | |
375 | case eSendMore: | |
376 | case eReadMessage: | |
377 | case eReadPayload: | |
378 | case eReadMore: | |
379 | case eReadFile: | |
380 | ev_io_start(event_base, &IO->send_event); | |
381 | break; | |
382 | case eDBQuery: | |
383 | StopClientWatchers(IO, 0); | |
384 | default: | |
385 | break; | |
386 | } | |
372 | 387 | break; |
373 | 388 | case eReadPayload: |
374 | 389 | case eReadMore: |
205 | 205 | if (IsEmptyStr(filename)) { |
206 | 206 | cprintf("%d You must specify a file name.\n", |
207 | 207 | ERROR + FILE_NOT_FOUND); |
208 | return; | |
209 | } | |
210 | if (strstr(filename, "../") != NULL) | |
211 | { | |
212 | cprintf("%d syntax error.\n", | |
213 | ERROR + ILLEGAL_VALUE); | |
208 | 214 | return; |
209 | 215 | } |
210 | 216 | |
288 | 294 | filename[a] = '_'; |
289 | 295 | } |
290 | 296 | } |
297 | if (strstr(filename, "../") != NULL) | |
298 | { | |
299 | cprintf("%d syntax error.\n", | |
300 | ERROR + ILLEGAL_VALUE); | |
301 | return; | |
302 | } | |
303 | ||
291 | 304 | snprintf(pathname, sizeof pathname, |
292 | 305 | "%s/%s", |
293 | 306 | ctdl_image_dir, |
304 | 304 | |
305 | 305 | void DestructCAres(AsyncIO *IO) |
306 | 306 | { |
307 | EV_DNS_syslog(LOG_DEBUG, "C-ARES: %s\n", __FUNCTION__); | |
308 | ||
309 | EV_DNS_LOG_STOP(DNS.recv_event); | |
307 | EVNC_syslog(LOG_DEBUG, "C-ARES: %s\n", __FUNCTION__); | |
308 | ||
309 | EVNC_syslog(LOG_DEBUG, "C-ARES: - stopping %s %d %p \n", "DNS.recv_event", IO->DNS.recv_event.fd, &IO->DNS.recv_event); | |
310 | 310 | ev_io_stop(event_base, &IO->DNS.recv_event); |
311 | 311 | |
312 | EV_DNS_LOG_STOP(DNS.send_event); | |
312 | EVNC_syslog(LOG_DEBUG, "C-ARES: - stopping %s %d %p\n", "DNS.send_event", IO->DNS.send_event.fd, &IO->DNS.send_event); | |
313 | 313 | ev_io_stop(event_base, &IO->DNS.send_event); |
314 | 314 | |
315 | EV_DNS_LOGT_STOP(DNS.timeout); | |
315 | EVNC_syslog(LOG_DEBUG, "C-ARES: - stopping %s %p\n", "DNS.timeout", &IO->DNS.send_event); | |
316 | 316 | ev_timer_stop (event_base, &IO->DNS.timeout); |
317 | 317 | |
318 | EV_DNS_LOGT_STOP(unwind_stack); | |
318 | EVNC_syslog(LOG_DEBUG, "C-ARES: - stopping %s %p\n", "DNS.unwind_stack", &IO->unwind_stack); | |
319 | 319 | ev_idle_stop(event_base, &IO->unwind_stack); |
320 | 320 | ares_destroy_options(&IO->DNS.Options); |
321 | 321 | } |
210 | 210 | struct cdbdata *cdboi; |
211 | 211 | long usernum = 0L; |
212 | 212 | |
213 | if (config.c_disable_newu) | |
214 | { | |
215 | cprintf("%d this system does not support openid.\n", | |
216 | ERROR + CMD_NOT_SUPPORTED); | |
217 | return; | |
218 | } | |
213 | 219 | if (CtdlAccessCheck(ac_logged_in)) return; |
220 | ||
214 | 221 | cdb_rewind(CDB_OPENID); |
215 | 222 | cprintf("%d Associated OpenIDs:\n", LISTING_FOLLOWS); |
216 | 223 | |
235 | 242 | long usernum; |
236 | 243 | struct ctdluser usbuf; |
237 | 244 | |
245 | if (config.c_disable_newu) | |
246 | { | |
247 | cprintf("%d this system does not support openid.\n", | |
248 | ERROR + CMD_NOT_SUPPORTED); | |
249 | return; | |
250 | } | |
238 | 251 | if (CtdlAccessCheck(ac_aide)) return; |
239 | 252 | cdb_rewind(CDB_OPENID); |
240 | 253 | cprintf("%d List of all OpenIDs in the database:\n", LISTING_FOLLOWS); |
264 | 277 | void cmd_oidc(char *argbuf) { |
265 | 278 | ctdl_openid *oiddata = (ctdl_openid *) CC->openid_data; |
266 | 279 | |
280 | if (config.c_disable_newu) | |
281 | { | |
282 | cprintf("%d this system does not support openid.\n", | |
283 | ERROR + CMD_NOT_SUPPORTED); | |
284 | return; | |
285 | } | |
267 | 286 | if ( (!oiddata) || (!oiddata->verified) ) { |
268 | 287 | cprintf("%d You have not verified an OpenID yet.\n", ERROR); |
269 | 288 | return; |
291 | 310 | int this_is_mine = 0; |
292 | 311 | long usernum = 0L; |
293 | 312 | |
313 | if (config.c_disable_newu) | |
314 | { | |
315 | cprintf("%d this system does not support openid.\n", | |
316 | ERROR + CMD_NOT_SUPPORTED); | |
317 | return; | |
318 | } | |
294 | 319 | if (CtdlAccessCheck(ac_logged_in)) return; |
295 | 320 | extract_token(id_to_detach, argbuf, 0, '|', sizeof id_to_detach); |
296 | 321 | if (IsEmptyStr(id_to_detach)) { |
806 | 831 | ctdl_openid *oiddata; |
807 | 832 | int discovery_succeeded = 0; |
808 | 833 | |
834 | if (config.c_disable_newu) | |
835 | { | |
836 | cprintf("%d this system does not support openid.\n", | |
837 | ERROR + CMD_NOT_SUPPORTED); | |
838 | return; | |
839 | } | |
809 | 840 | Free_ctdl_openid ((ctdl_openid**)&CCC->openid_data); |
810 | 841 | |
811 | 842 | CCC->openid_data = oiddata = malloc(sizeof(ctdl_openid)); |
931 | 962 | void *Value; |
932 | 963 | ctdl_openid *oiddata = (ctdl_openid *) CC->openid_data; |
933 | 964 | |
965 | if (config.c_disable_newu) | |
966 | { | |
967 | cprintf("%d this system does not support openid.\n", | |
968 | ERROR + CMD_NOT_SUPPORTED); | |
969 | return; | |
970 | } | |
934 | 971 | if (oiddata == NULL) { |
935 | 972 | cprintf("%d run OIDS first.\n", ERROR + INTERNAL_ERROR); |
936 | 973 | return; |
196 | 196 | FreeStrBuf(&ptr->IO.SendBuf.Buf); |
197 | 197 | FreeStrBuf(&ptr->IO.RecvBuf.Buf); |
198 | 198 | DeleteAsyncMsg(&ptr->IO.ReadMsg); |
199 | ((struct CitContext*)ptr->IO.CitContext)->state = CON_IDLE; | |
200 | ((struct CitContext*)ptr->IO.CitContext)->kill_me = 1; | |
199 | if (((struct CitContext*)ptr->IO.CitContext)) { | |
200 | ((struct CitContext*)ptr->IO.CitContext)->state = CON_IDLE; | |
201 | ((struct CitContext*)ptr->IO.CitContext)->kill_me = 1; | |
202 | } | |
201 | 203 | FreeAsyncIOContents(&ptr->IO); |
202 | 204 | free(ptr); |
203 | 205 | } |
152 | 152 | |
153 | 153 | Msg->IDestructQueItem = DecreaseQReference(Msg->MyQItem); |
154 | 154 | |
155 | Msg->nRemain = CountActiveQueueEntries(Msg->MyQItem); | |
155 | Msg->nRemain = CountActiveQueueEntries(Msg->MyQItem, 0); | |
156 | 156 | |
157 | 157 | if (Msg->MyQEntry->Active && |
158 | !Msg->MyQEntry->StillActive && | |
158 | 159 | CheckQEntryIsBounce(Msg->MyQEntry)) |
159 | 160 | { |
160 | 161 | /* are we casue for a bounce mail? */ |
175 | 176 | Msg->MyQItem->QueMsgID = -1; |
176 | 177 | |
177 | 178 | if (Msg->IDestructQueItem) |
178 | smtpq_do_bounce(Msg->MyQItem, Msg->msgtext); | |
179 | smtpq_do_bounce(Msg->MyQItem, Msg->msgtext, Msg->pCurrRelay); | |
179 | 180 | |
180 | 181 | if (Msg->nRemain > 0) |
181 | 182 | { |
245 | 245 | return 0; |
246 | 246 | } |
247 | 247 | |
248 | int CountActiveQueueEntries(OneQueItem *MyQItem) | |
248 | int CountActiveQueueEntries(OneQueItem *MyQItem, int before) | |
249 | 249 | { |
250 | 250 | HashPos *It; |
251 | 251 | long len; |
257 | 257 | It = GetNewHashPos(MyQItem->MailQEntries, 0); |
258 | 258 | while (GetNextHashPos(MyQItem->MailQEntries, It, &len, &Key, &vQE)) |
259 | 259 | { |
260 | int Active; | |
260 | 261 | MailQEntry *ThisItem = vQE; |
261 | 262 | |
262 | 263 | if (CheckQEntryActive(ThisItem)) |
263 | 264 | { |
264 | 265 | ActiveDeliveries++; |
265 | ThisItem->Active = 1; | |
266 | Active = 1; | |
266 | 267 | } |
267 | 268 | else |
268 | ThisItem->Active = 0; | |
269 | Active = 0; | |
270 | if (before) | |
271 | ThisItem->Active = Active; | |
272 | else | |
273 | ThisItem->StillActive = Active; | |
269 | 274 | } |
270 | 275 | DeleteHashPos(&It); |
271 | 276 | return ActiveDeliveries; |
504 | 509 | * instructions for "5" codes (permanent fatal errors) and produce/deliver |
505 | 510 | * a "bounce" message (delivery status notification). |
506 | 511 | */ |
507 | void smtpq_do_bounce(OneQueItem *MyQItem, StrBuf *OMsgTxt) | |
512 | void smtpq_do_bounce(OneQueItem *MyQItem, StrBuf *OMsgTxt, ParsedURL *Relay) | |
508 | 513 | { |
509 | 514 | static int seq = 0; |
510 | 515 | |
555 | 560 | { |
556 | 561 | ++num_bounces; |
557 | 562 | |
563 | StrBufAppendBufPlain(Msg, HKEY(" "), 0); | |
558 | 564 | StrBufAppendBuf(Msg, ThisItem->Recipient, 0); |
559 | 565 | StrBufAppendBufPlain(Msg, HKEY(": "), 0); |
560 | 566 | StrBufAppendBuf(Msg, ThisItem->StatusMessage, 0); |
569 | 575 | if (num_bounces == 0) { |
570 | 576 | FreeStrBuf(&Msg); |
571 | 577 | return; |
578 | } | |
579 | ||
580 | if ((StrLength(MyQItem->SenderRoom) == 0) && MyQItem->HaveRelay) { | |
581 | /* one message that relaying is broken is enough; no extra room error message. */ | |
582 | StrBuf *RelayDetails = NewStrBuf(); | |
583 | ||
584 | StrBufPrintf(RelayDetails, | |
585 | "Relaying via %s failed permanently. \n Reason:\n%s\n Revalidate your relay configuration.", | |
586 | ChrPtr(Relay->URL), | |
587 | ChrPtr(Msg)); | |
588 | CtdlAideMessage(ChrPtr(RelayDetails), "Relaying Failed"); | |
589 | FreeStrBuf(&RelayDetails); | |
572 | 590 | } |
573 | 591 | |
574 | 592 | boundary = NewStrBufPlain(HKEY("=_Citadel_Multipart_")); |
883 | 901 | DeleteHashPos(&It); |
884 | 902 | |
885 | 903 | MyQItem->NotYetShutdownDeliveries = |
886 | MyQItem->ActiveDeliveries = CountActiveQueueEntries(MyQItem); | |
904 | MyQItem->ActiveDeliveries = CountActiveQueueEntries(MyQItem, 1); | |
887 | 905 | |
888 | 906 | /* failsafe against overload: |
889 | 907 | * will we exceed the limit set? |
112 | 112 | #define SMTP_DBG_READ() \ |
113 | 113 | EVS_syslog(LOG_DEBUG, "< %s\n", ChrPtr(Msg->IO.IOBuf)) |
114 | 114 | |
115 | /* | |
116 | * if a Read handler wants to skip to a specific part use this macro. | |
117 | * the -1 is here since the auto-forward following has to be taken into account. | |
118 | */ | |
119 | #define READ_NEXT_STATE(state) Msg->State = state - 1 | |
115 | 120 | |
116 | 121 | /*****************************************************************************/ |
117 | 122 | /* SMTP CLIENT STATE CALLBACKS */ |
150 | 155 | SMTP_DBG_READ(); |
151 | 156 | |
152 | 157 | if (SMTP_IS_STATE('2')) { |
153 | Msg->State ++; | |
158 | READ_NEXT_STATE(eSMTPAuth); | |
154 | 159 | |
155 | 160 | if ((Msg->pCurrRelay == NULL) || |
156 | 161 | (Msg->pCurrRelay->User == NULL)) |
157 | Msg->State ++; /* Skip auth... */ | |
162 | READ_NEXT_STATE(eFROM); /* Skip auth... */ | |
163 | if (Msg->pCurrRelay != NULL) | |
164 | { | |
165 | if (strstr(ChrPtr(Msg->IO.IOBuf), "LOGIN") != NULL) | |
166 | Msg->SendLogin = 1; | |
167 | } | |
158 | 168 | } |
159 | 169 | /* else we fall back to 'helo' */ |
160 | 170 | return eSendReply; |
184 | 194 | } |
185 | 195 | if ((Msg->pCurrRelay == NULL) || |
186 | 196 | (Msg->pCurrRelay->User == NULL)) |
187 | Msg->State ++; /* Skip auth... */ | |
197 | READ_NEXT_STATE(eFROM); /* Skip auth... */ | |
188 | 198 | |
189 | 199 | return eSendReply; |
190 | 200 | } |
197 | 207 | |
198 | 208 | if ((Msg->pCurrRelay == NULL) || |
199 | 209 | (Msg->pCurrRelay->User == NULL)) |
200 | Msg->State ++; /* Skip auth, shouldn't even come here!... */ | |
210 | READ_NEXT_STATE(eFROM); /* Skip auth, shouldn't even come here!... */ | |
201 | 211 | else { |
202 | 212 | /* Do an AUTH command if necessary */ |
203 | sprintf(buf, "%s%c%s%c%s", | |
204 | Msg->pCurrRelay->User, '\0', | |
205 | Msg->pCurrRelay->User, '\0', | |
206 | Msg->pCurrRelay->Pass); | |
207 | ||
208 | CtdlEncodeBase64(encoded, buf, | |
209 | strlen(Msg->pCurrRelay->User) * 2 + | |
210 | strlen(Msg->pCurrRelay->Pass) + 2, 0); | |
211 | ||
212 | StrBufPrintf(Msg->IO.SendBuf.Buf, | |
213 | "AUTH PLAIN %s\r\n", encoded); | |
214 | } | |
215 | SMTP_DBG_SEND(); | |
216 | return eReadMessage; | |
217 | } | |
213 | if (Msg->SendLogin) | |
214 | { | |
215 | StrBufPlain(Msg->IO.SendBuf.Buf, | |
216 | HKEY("AUTH LOGIN\r\n")); | |
217 | } | |
218 | else | |
219 | { | |
220 | sprintf(buf, "%s%c%s%c%s", | |
221 | Msg->pCurrRelay->User, '\0', | |
222 | Msg->pCurrRelay->User, '\0', | |
223 | Msg->pCurrRelay->Pass); | |
224 | ||
225 | CtdlEncodeBase64(encoded, buf, | |
226 | strlen(Msg->pCurrRelay->User) * 2 + | |
227 | strlen(Msg->pCurrRelay->Pass) + 2, 0); | |
228 | ||
229 | StrBufPrintf(Msg->IO.SendBuf.Buf, | |
230 | "AUTH PLAIN %s\r\n", | |
231 | encoded); | |
232 | } | |
233 | } | |
234 | SMTP_DBG_SEND(); | |
235 | return eReadMessage; | |
236 | } | |
237 | ||
218 | 238 | |
219 | 239 | eNextState SMTPC_read_auth_reply(SmtpOutMsg *Msg) |
240 | { | |
241 | AsyncIO *IO = &Msg->IO; | |
242 | /* Do an AUTH command if necessary */ | |
243 | ||
244 | SMTP_DBG_READ(); | |
245 | ||
246 | if (Msg->SendLogin) | |
247 | { | |
248 | if (!SMTP_IS_STATE('3')) | |
249 | SMTP_VERROR(5); | |
250 | } | |
251 | else | |
252 | { | |
253 | if (!SMTP_IS_STATE('2')) { | |
254 | if (SMTP_IS_STATE('4')) | |
255 | SMTP_VERROR(4); | |
256 | else | |
257 | SMTP_VERROR(5); | |
258 | } | |
259 | READ_NEXT_STATE(eFROM); | |
260 | } | |
261 | return eSendReply; | |
262 | } | |
263 | ||
264 | ||
265 | eNextState SMTPC_send_authplain_1(SmtpOutMsg *Msg) | |
266 | { | |
267 | AsyncIO *IO = &Msg->IO; | |
268 | char buf[SIZ]; | |
269 | char encoded[1024]; | |
270 | long encodedlen; | |
271 | ||
272 | sprintf(buf, "%s", | |
273 | Msg->pCurrRelay->User); | |
274 | ||
275 | encodedlen = CtdlEncodeBase64( | |
276 | encoded, | |
277 | Msg->pCurrRelay->User, | |
278 | strlen(Msg->pCurrRelay->User), | |
279 | 0); | |
280 | ||
281 | StrBufPlain(Msg->IO.SendBuf.Buf, | |
282 | encoded, | |
283 | encodedlen); | |
284 | ||
285 | StrBufAppendBufPlain(Msg->IO.SendBuf.Buf, | |
286 | HKEY("\r\n"), 0); | |
287 | ||
288 | SMTP_DBG_SEND(); | |
289 | ||
290 | return eReadMessage; | |
291 | } | |
292 | eNextState SMTPC_read_auth_plain_reply_1(SmtpOutMsg *Msg) | |
293 | { | |
294 | AsyncIO *IO = &Msg->IO; | |
295 | /* Do an AUTH command if necessary */ | |
296 | ||
297 | SMTP_DBG_READ(); | |
298 | ||
299 | if (!SMTP_IS_STATE('3')) | |
300 | SMTP_VERROR(5); | |
301 | return eSendReply; | |
302 | } | |
303 | ||
304 | ||
305 | eNextState SMTPC_send_authplain_2(SmtpOutMsg *Msg) | |
306 | { | |
307 | AsyncIO *IO = &Msg->IO; | |
308 | char buf[SIZ]; | |
309 | char encoded[1024]; | |
310 | long encodedlen; | |
311 | ||
312 | sprintf(buf, "%s", | |
313 | Msg->pCurrRelay->Pass); | |
314 | ||
315 | encodedlen = CtdlEncodeBase64( | |
316 | encoded, | |
317 | Msg->pCurrRelay->User, | |
318 | strlen(Msg->pCurrRelay->User), | |
319 | 0); | |
320 | ||
321 | StrBufPlain(Msg->IO.SendBuf.Buf, | |
322 | encoded, | |
323 | encodedlen); | |
324 | ||
325 | StrBufAppendBufPlain(Msg->IO.SendBuf.Buf, | |
326 | HKEY("\r\n"), 0); | |
327 | ||
328 | SMTP_DBG_SEND(); | |
329 | ||
330 | return eReadMessage; | |
331 | } | |
332 | eNextState SMTPC_read_auth_plain_reply_2(SmtpOutMsg *Msg) | |
220 | 333 | { |
221 | 334 | AsyncIO *IO = &Msg->IO; |
222 | 335 | /* Do an AUTH command if necessary */ |
319 | 432 | Buf = Msg->IO.SendBuf.Buf; |
320 | 433 | Msg->IO.SendBuf.Buf = Msg->msgtext; |
321 | 434 | Msg->msgtext = Buf; |
435 | /* | |
436 | * sending the message itself doesn't use this state machine. | |
437 | * so we have to operate it here by ourselves. | |
438 | */ | |
322 | 439 | Msg->State ++; |
323 | 440 | |
324 | 441 | return eSendMore; |
402 | 519 | SMTPC_read_EHLO_reply, |
403 | 520 | SMTPC_read_HELO_reply, |
404 | 521 | SMTPC_read_auth_reply, |
522 | SMTPC_read_auth_plain_reply_1, | |
523 | SMTPC_read_auth_plain_reply_2, | |
405 | 524 | SMTPC_read_FROM_reply, |
406 | 525 | SMTPC_read_RCPT_reply, |
407 | 526 | SMTPC_read_DATAcmd_reply, |
414 | 533 | SMTPC_send_EHLO, |
415 | 534 | STMPC_send_HELO, |
416 | 535 | SMTPC_send_auth, |
536 | SMTPC_send_authplain_1, | |
537 | SMTPC_send_authplain_2, | |
417 | 538 | SMTPC_send_FROM, |
418 | 539 | SMTPC_send_RCPT, |
419 | 540 | SMTPC_send_DATAcmd, |
428 | 549 | 300., /* Greeting... */ |
429 | 550 | 30., /* EHLO */ |
430 | 551 | 30., /* HELO */ |
552 | 30., /* Auth */ | |
553 | 30., /* Auth */ | |
431 | 554 | 30., /* Auth */ |
432 | 555 | 30., /* From */ |
433 | 556 | 90., /* RCPT */ |
441 | 564 | 30., /* EHLO */ |
442 | 565 | 30., /* HELO */ |
443 | 566 | 30., /* Auth */ |
567 | 30., /* Auth */ | |
568 | 30., /* Auth */ | |
444 | 569 | 30., /* From */ |
445 | 570 | 30., /* RCPT */ |
446 | 571 | 30., /* DATA */ |
454 | 579 | {HKEY("Connection broken during SMTP EHLO")}, |
455 | 580 | {HKEY("Connection broken during SMTP HELO")}, |
456 | 581 | {HKEY("Connection broken during SMTP AUTH")}, |
582 | {HKEY("Connection broken during SMTP AUTH PLAIN I")}, | |
583 | {HKEY("Connection broken during SMTP AUTH PLAIN II")}, | |
457 | 584 | {HKEY("Connection broken during SMTP MAIL FROM")}, |
458 | 585 | {HKEY("Connection broken during SMTP RCPT")}, |
459 | 586 | {HKEY("Connection broken during SMTP DATA")}, |
21 | 21 | eEHLO, |
22 | 22 | eHELO, |
23 | 23 | eSMTPAuth, |
24 | eSMTPAuthPlain1, | |
25 | eSMTPAuthPlain2, | |
24 | 26 | eFROM, |
25 | 27 | eRCPT, |
26 | 28 | eDATA, |
66 | 68 | char name[1024]; |
67 | 69 | char mailfrom[1024]; |
68 | 70 | |
71 | long SendLogin; | |
69 | 72 | long Flags; |
70 | 73 | } SmtpOutMsg; |
71 | 74 |
39 | 39 | |
40 | 40 | int n; |
41 | 41 | int Active; |
42 | int StillActive; | |
42 | 43 | }MailQEntry; |
43 | 44 | |
44 | 45 | typedef struct queueitem { |
75 | 76 | void DecreaseShutdownDeliveries(OneQueItem *MyQItem); |
76 | 77 | int GetShutdownDeliveries(OneQueItem *MyQItem); |
77 | 78 | void RemoveQItem(OneQueItem *MyQItem); |
78 | int CountActiveQueueEntries(OneQueItem *MyQItem); | |
79 | int CountActiveQueueEntries(OneQueItem *MyQItem, int before); | |
79 | 80 | StrBuf *SerializeQueueItem(OneQueItem *MyQItem); |
80 | void smtpq_do_bounce(OneQueItem *MyQItem, StrBuf *OMsgTxt); | |
81 | void smtpq_do_bounce(OneQueItem *MyQItem, StrBuf *OMsgTxt, ParsedURL *Relay); | |
81 | 82 | |
82 | 83 | int CheckQEntryIsBounce(MailQEntry *ThisItem); |
328 | 328 | * and in the global address book). |
329 | 329 | */ |
330 | 330 | int vcard_upload_beforesave(struct CtdlMessage *msg) { |
331 | struct CitContext *CCC = CC; | |
331 | 332 | char *ptr; |
332 | 333 | char *s; |
333 | 334 | char buf[SIZ]; |
339 | 340 | int yes_my_citadel_config = 0; |
340 | 341 | int yes_any_vcard_room = 0; |
341 | 342 | |
342 | if (!CC->logged_in) return(0); /* Only do this if logged in. */ | |
343 | if (!CCC->logged_in) return(0); /* Only do this if logged in. */ | |
343 | 344 | |
344 | 345 | /* Is this some user's "My Citadel Config" room? */ |
345 | if ( (CC->room.QRflags && QR_MAILBOX) | |
346 | && (!strcasecmp(&CC->room.QRname[11], USERCONFIGROOM)) ) { | |
346 | if (((CCC->room.QRflags & QR_MAILBOX) != 0) && | |
347 | (!strcasecmp(&CCC->room.QRname[11], USERCONFIGROOM)) ) { | |
347 | 348 | /* Yes, we want to do this */ |
348 | 349 | yes_my_citadel_config = 1; |
349 | 350 | |
350 | 351 | #ifdef VCARD_SAVES_BY_AIDES_ONLY |
351 | 352 | /* Prevent non-aides from performing registration changes */ |
352 | if (CC->user.axlevel < AxAideU) { | |
353 | if (CCC->user.axlevel < AxAideU) { | |
353 | 354 | return(1); |
354 | 355 | } |
355 | 356 | #endif |
357 | 358 | } |
358 | 359 | |
359 | 360 | /* Is this a room with an address book in it? */ |
360 | if (CC->room.QRdefaultview == VIEW_ADDRESSBOOK) { | |
361 | if (CCC->room.QRdefaultview == VIEW_ADDRESSBOOK) { | |
361 | 362 | yes_any_vcard_room = 1; |
362 | 363 | } |
363 | 364 | |
385 | 386 | if (v == NULL) return(0); /* no vCards were found in this message */ |
386 | 387 | |
387 | 388 | /* If users cannot create their own accounts, they cannot re-register either. */ |
388 | if ( (yes_my_citadel_config) && (config.c_disable_newu) && (CC->user.axlevel < AxAideU) ) { | |
389 | if ( (yes_my_citadel_config) && (config.c_disable_newu) && (CCC->user.axlevel < AxAideU) ) { | |
389 | 390 | return(1); |
390 | 391 | } |
391 | 392 | |
396 | 397 | * delete the old one. First, figure out which user |
397 | 398 | * is being re-registered... |
398 | 399 | */ |
399 | what_user = atol(CC->room.QRname); | |
400 | ||
401 | if (what_user == CC->user.usernum) { | |
400 | what_user = atol(CCC->room.QRname); | |
401 | ||
402 | if (what_user == CCC->user.usernum) { | |
402 | 403 | /* It's the logged in user. That was easy. */ |
403 | memcpy(&usbuf, &CC->user, sizeof(struct ctdluser)); | |
404 | memcpy(&usbuf, &CCC->user, sizeof(struct ctdluser)); | |
404 | 405 | } |
405 | 406 | |
406 | 407 | else if (CtdlGetUserByNumber(&usbuf, what_user) == 0) { |
420 | 421 | * vCard in the user's config room at all times. |
421 | 422 | * |
422 | 423 | */ |
423 | CtdlDeleteMessages(CC->room.QRname, NULL, 0, "[Tt][Ee][Xx][Tt]/.*[Vv][Cc][Aa][Rr][Dd]$"); | |
424 | CtdlDeleteMessages(CCC->room.QRname, NULL, 0, "[Tt][Ee][Xx][Tt]/.*[Vv][Cc][Aa][Rr][Dd]$"); | |
424 | 425 | |
425 | 426 | /* Make the author of the message the name of the user. */ |
426 | 427 | if (msg->cm_fields['A'] != NULL) { |
507 | 508 | * address book). |
508 | 509 | */ |
509 | 510 | int vcard_upload_aftersave(struct CtdlMessage *msg) { |
511 | struct CitContext *CCC = CC; | |
510 | 512 | char *ptr; |
511 | 513 | int linelen; |
512 | 514 | long I; |
517 | 519 | char roomname[ROOMNAMELEN]; |
518 | 520 | |
519 | 521 | if (msg->cm_format_type != 4) return(0); |
520 | if (!CC->logged_in) return(0); /* Only do this if logged in. */ | |
522 | if (!CCC->logged_in) return(0); /* Only do this if logged in. */ | |
521 | 523 | |
522 | 524 | /* We're interested in user config rooms only. */ |
523 | 525 | |
524 | if ( (strlen(CC->room.QRname) >= 12) && (!strcasecmp(&CC->room.QRname[11], USERCONFIGROOM)) ) { | |
526 | if ( (strlen(CCC->room.QRname) >= 12) && (!strcasecmp(&CCC->room.QRname[11], USERCONFIGROOM)) ) { | |
525 | 527 | is_UserConf = 1; /* It's someone's config room */ |
526 | 528 | } |
527 | CtdlMailboxName(roomname, sizeof roomname, &CC->user, USERCONFIGROOM); | |
528 | if (!strcasecmp(CC->room.QRname, roomname)) { | |
529 | CtdlMailboxName(roomname, sizeof roomname, &CCC->user, USERCONFIGROOM); | |
530 | if (!strcasecmp(CCC->room.QRname, roomname)) { | |
529 | 531 | is_UserConf = 1; |
530 | 532 | is_MY_UserConf = 1; /* It's MY config room */ |
531 | 533 | } |
532 | if (!strcasecmp(CC->room.QRname, ADDRESS_BOOK_ROOM)) { | |
534 | if (!strcasecmp(CCC->room.QRname, ADDRESS_BOOK_ROOM)) { | |
533 | 535 | is_GAB = 1; /* It's the Global Address Book */ |
534 | 536 | } |
535 | 537 | |
538 | 540 | ptr = msg->cm_fields['M']; |
539 | 541 | if (ptr == NULL) return(0); |
540 | 542 | |
541 | NewStrBufDupAppendFlush(&CC->StatusMessage, NULL, NULL, 0); | |
542 | ||
543 | StrBufPrintf(CC->StatusMessage, "%d\n", LISTING_FOLLOWS); | |
543 | NewStrBufDupAppendFlush(&CCC->StatusMessage, NULL, NULL, 0); | |
544 | ||
545 | StrBufPrintf(CCC->StatusMessage, "%d\n", LISTING_FOLLOWS); | |
544 | 546 | |
545 | 547 | while (ptr != NULL) { |
546 | 548 | |
560 | 562 | /* Store our Internet return address in memory */ |
561 | 563 | if (is_MY_UserConf) { |
562 | 564 | v = vcard_load(msg->cm_fields['M']); |
563 | extract_inet_email_addrs(CC->cs_inet_email, sizeof CC->cs_inet_email, | |
564 | CC->cs_inet_other_emails, sizeof CC->cs_inet_other_emails, | |
565 | extract_inet_email_addrs(CCC->cs_inet_email, sizeof CCC->cs_inet_email, | |
566 | CCC->cs_inet_other_emails, sizeof CCC->cs_inet_other_emails, | |
565 | 567 | v, 1); |
566 | extract_friendly_name(CC->cs_inet_fn, sizeof CC->cs_inet_fn, v); | |
568 | extract_friendly_name(CCC->cs_inet_fn, sizeof CCC->cs_inet_fn, v); | |
567 | 569 | vcard_free(v); |
568 | 570 | } |
569 | 571 | |
581 | 583 | * But if the user was an Aide or was edited by an Aide then we can |
582 | 584 | * Assume they don't need validating. |
583 | 585 | */ |
584 | if (CC->user.axlevel >= AxAideU) { | |
585 | CtdlGetUserLock(&CC->user, CC->curr_user); | |
586 | CC->user.flags |= US_REGIS; | |
587 | CtdlPutUserLock(&CC->user); | |
586 | if (CCC->user.axlevel >= AxAideU) { | |
587 | CtdlGetUserLock(&CCC->user, CCC->curr_user); | |
588 | CCC->user.flags |= US_REGIS; | |
589 | CtdlPutUserLock(&CCC->user); | |
588 | 590 | return (0); |
589 | 591 | } |
590 | 592 | |
591 | 593 | set_mm_valid(); |
592 | 594 | |
593 | 595 | /* ...which also means we need to flag the user */ |
594 | CtdlGetUserLock(&CC->user, CC->curr_user); | |
595 | CC->user.flags |= (US_REGIS|US_NEEDVALID); | |
596 | CtdlPutUserLock(&CC->user); | |
596 | CtdlGetUserLock(&CCC->user, CCC->curr_user); | |
597 | CCC->user.flags |= (US_REGIS|US_NEEDVALID); | |
598 | CtdlPutUserLock(&CCC->user); | |
597 | 599 | |
598 | 600 | return(0); |
599 | 601 | } |
623 | 625 | * and return an empty vCard. |
624 | 626 | */ |
625 | 627 | struct vCard *vcard_get_user(struct ctdluser *u) { |
628 | struct CitContext *CCC = CC; | |
626 | 629 | char hold_rm[ROOMNAMELEN]; |
627 | 630 | char config_rm[ROOMNAMELEN]; |
628 | 631 | struct CtdlMessage *msg = NULL; |
629 | 632 | struct vCard *v; |
630 | 633 | long VCmsgnum; |
631 | 634 | |
632 | strcpy(hold_rm, CC->room.QRname); /* save current room */ | |
635 | strcpy(hold_rm, CCC->room.QRname); /* save current room */ | |
633 | 636 | CtdlMailboxName(config_rm, sizeof config_rm, u, USERCONFIGROOM); |
634 | 637 | |
635 | if (CtdlGetRoom(&CC->room, config_rm) != 0) { | |
636 | CtdlGetRoom(&CC->room, hold_rm); | |
638 | if (CtdlGetRoom(&CCC->room, config_rm) != 0) { | |
639 | CtdlGetRoom(&CCC->room, hold_rm); | |
637 | 640 | return vcard_new(); |
638 | 641 | } |
639 | 642 | |
641 | 644 | VCmsgnum = (-1); |
642 | 645 | CtdlForEachMessage(MSGS_LAST, 1, NULL, "[Tt][Ee][Xx][Tt]/.*[Vv][Cc][Aa][Rr][Dd]$", |
643 | 646 | NULL, vcard_gu_backend, (void *)&VCmsgnum ); |
644 | CtdlGetRoom(&CC->room, hold_rm); /* return to saved room */ | |
647 | CtdlGetRoom(&CCC->room, hold_rm); /* return to saved room */ | |
645 | 648 | |
646 | 649 | if (VCmsgnum < 0L) return vcard_new(); |
647 | 650 | |
695 | 698 | * and enters the vCard into the user's configuration. |
696 | 699 | */ |
697 | 700 | void cmd_regi(char *argbuf) { |
701 | struct CitContext *CCC = CC; | |
698 | 702 | int a,b,c; |
699 | 703 | char buf[SIZ]; |
700 | 704 | struct vCard *my_vcard; |
708 | 712 | |
709 | 713 | unbuffer_output(); |
710 | 714 | |
711 | if (!(CC->logged_in)) { | |
715 | if (!(CCC->logged_in)) { | |
712 | 716 | cprintf("%d Not logged in.\n",ERROR + NOT_LOGGED_IN); |
713 | 717 | return; |
714 | 718 | } |
715 | 719 | |
716 | 720 | /* If users cannot create their own accounts, they cannot re-register either. */ |
717 | if ( (config.c_disable_newu) && (CC->user.axlevel < AxAideU) ) { | |
721 | if ( (config.c_disable_newu) && (CCC->user.axlevel < AxAideU) ) { | |
718 | 722 | cprintf("%d Self-service registration is not allowed here.\n", |
719 | 723 | ERROR + HIGHER_ACCESS_REQUIRED); |
720 | 724 | } |
721 | 725 | |
722 | my_vcard = vcard_get_user(&CC->user); | |
726 | my_vcard = vcard_get_user(&CCC->user); | |
723 | 727 | strcpy(tmpaddr, ""); |
724 | 728 | strcpy(tmpcity, ""); |
725 | 729 | strcpy(tmpstate, ""); |
751 | 755 | snprintf(tmpaddress, sizeof tmpaddress, ";;%s;%s;%s;%s;%s", |
752 | 756 | tmpaddr, tmpcity, tmpstate, tmpzip, tmpcountry); |
753 | 757 | vcard_set_prop(my_vcard, "adr", tmpaddress, 0); |
754 | vcard_write_user(&CC->user, my_vcard); | |
758 | vcard_write_user(&CCC->user, my_vcard); | |
755 | 759 | vcard_free(my_vcard); |
756 | 760 | } |
757 | 761 | |
761 | 765 | */ |
762 | 766 | void cmd_greg(char *argbuf) |
763 | 767 | { |
768 | struct CitContext *CCC = CC; | |
764 | 769 | struct ctdluser usbuf; |
765 | 770 | struct vCard *v; |
766 | 771 | char *s; |
770 | 775 | |
771 | 776 | extract_token(who, argbuf, 0, '|', sizeof who); |
772 | 777 | |
773 | if (!(CC->logged_in)) { | |
778 | if (!(CCC->logged_in)) { | |
774 | 779 | cprintf("%d Not logged in.\n", ERROR + NOT_LOGGED_IN); |
775 | 780 | return; |
776 | 781 | } |
777 | 782 | |
778 | if (!strcasecmp(who,"_SELF_")) strcpy(who,CC->curr_user); | |
779 | ||
780 | if ((CC->user.axlevel < AxAideU) && (strcasecmp(who,CC->curr_user))) { | |
783 | if (!strcasecmp(who,"_SELF_")) strcpy(who,CCC->curr_user); | |
784 | ||
785 | if ((CCC->user.axlevel < AxAideU) && (strcasecmp(who,CCC->curr_user))) { | |
781 | 786 | cprintf("%d Higher access required.\n", |
782 | 787 | ERROR + HIGHER_ACCESS_REQUIRED); |
783 | 788 | return; |
998 | 1003 | */ |
999 | 1004 | void cmd_gvsn(char *argbuf) |
1000 | 1005 | { |
1006 | struct CitContext *CCC = CC; | |
1007 | ||
1001 | 1008 | if (CtdlAccessCheck(ac_logged_in)) return; |
1002 | 1009 | |
1003 | 1010 | cprintf("%d valid screen names:\n", LISTING_FOLLOWS); |
1004 | cprintf("%s\n", CC->user.fullname); | |
1005 | if ( (!IsEmptyStr(CC->cs_inet_fn)) && (strcasecmp(CC->user.fullname, CC->cs_inet_fn)) ) { | |
1006 | cprintf("%s\n", CC->cs_inet_fn); | |
1011 | cprintf("%s\n", CCC->user.fullname); | |
1012 | if ( (!IsEmptyStr(CCC->cs_inet_fn)) && (strcasecmp(CCC->user.fullname, CCC->cs_inet_fn)) ) { | |
1013 | cprintf("%s\n", CCC->cs_inet_fn); | |
1007 | 1014 | } |
1008 | 1015 | cprintf("000\n"); |
1009 | 1016 | } |
1014 | 1021 | */ |
1015 | 1022 | void cmd_gvea(char *argbuf) |
1016 | 1023 | { |
1024 | struct CitContext *CCC = CC; | |
1017 | 1025 | int num_secondary_emails = 0; |
1018 | 1026 | int i; |
1019 | 1027 | char buf[256]; |
1021 | 1029 | if (CtdlAccessCheck(ac_logged_in)) return; |
1022 | 1030 | |
1023 | 1031 | cprintf("%d valid email addresses:\n", LISTING_FOLLOWS); |
1024 | if (!IsEmptyStr(CC->cs_inet_email)) { | |
1025 | cprintf("%s\n", CC->cs_inet_email); | |
1026 | } | |
1027 | if (!IsEmptyStr(CC->cs_inet_other_emails)) { | |
1028 | num_secondary_emails = num_tokens(CC->cs_inet_other_emails, '|'); | |
1032 | if (!IsEmptyStr(CCC->cs_inet_email)) { | |
1033 | cprintf("%s\n", CCC->cs_inet_email); | |
1034 | } | |
1035 | if (!IsEmptyStr(CCC->cs_inet_other_emails)) { | |
1036 | num_secondary_emails = num_tokens(CCC->cs_inet_other_emails, '|'); | |
1029 | 1037 | for (i=0; i<num_secondary_emails; ++i) { |
1030 | extract_token(buf, CC->cs_inet_other_emails,i,'|',sizeof CC->cs_inet_other_emails); | |
1038 | extract_token(buf, CCC->cs_inet_other_emails,i,'|',sizeof CCC->cs_inet_other_emails); | |
1031 | 1039 | cprintf("%s\n", buf); |
1032 | 1040 | } |
1033 | 1041 | } |
1491 | 1499 | if (rv == -1) |
1492 | 1500 | syslog(LOG_EMERG, "Failed to adjust ownership of: %s [%s]", |
1493 | 1501 | filename, strerror(errno)); |
1502 | rv = chmod(filename, 0600); | |
1503 | if (rv == -1) | |
1504 | syslog(LOG_EMERG, "Failed to adjust ownership of: %s [%s]", | |
1505 | filename, strerror(errno)); | |
1494 | 1506 | } |
1495 | 1507 | |
1496 | 1508 | /* for postfix tcpdict */ |
203 | 203 | syslog(LOG_NOTICE, |
204 | 204 | "*** Citadel server engine v%d.%02d (build %s) ***", |
205 | 205 | (REV_LEVEL/100), (REV_LEVEL%100), svn_revision()); |
206 | syslog(LOG_NOTICE, "Copyright (C) 1987-2012 by the Citadel development team."); | |
206 | syslog(LOG_NOTICE, "Copyright (C) 1987-2013 by the Citadel development team."); | |
207 | 207 | syslog(LOG_NOTICE, "This program is distributed under the terms of the GNU " |
208 | 208 | "General Public License."); |
209 | 209 | syslog(LOG_NOTICE, " "); |