1 /*****************************************************************************
2 * HTICK --- FTN Ticker / Request Processor
3 *****************************************************************************
4 * Copyright (C) 1999 by
5 *
6 * Gabriel Plutzar
7 *
8 * Fido: 2:31/1
9 * Internet: gabriel@hit.priv.at
10 *
11 * Vienna, Austria, Europe
12 *
13 * This file is part of HTICK, which is based on HPT by Matthias Tichy,
14 * 2:2432/605.14 2:2433/1245, mtt@tichy.de
15 *
16 * HTICK is free software; you can redistribute it and/or modify it
17 * under the terms of the GNU General Public License as published by the
18 * Free Software Foundation; either version 2, or (at your option) any
19 * later version.
20 *
21 * HTICK is distributed in the hope that it will be useful, but
22 * WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with HTICK; see the file COPYING. If not, write to the Free
28 * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
29 *****************************************************************************
30 * $Id$
31 *****************************************************************************/
32
33 /* clib */
34 #include <string.h>
35 #include <stdlib.h>
36 #include <fcntl.h>
37 #include <errno.h>
38 #include <ctype.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41
42 /* compiler.h */
43 #include <huskylib/compiler.h>
44 #include <huskylib/huskylib.h>
45
46 #ifdef __OS2__
47 # define INCL_DOSFILEMGR /* for hidden() routine */
48 # include <os2.h>
49 #endif
50
51 #ifdef HAS_IO_H
52 # include <io.h>
53 #endif
54
55 #ifdef HAS_SHARE_H
56 # include <share.h>
57 #endif
58
59 #ifdef HAS_UNISTD_H
60 # include <unistd.h>
61 #endif
62
63 #ifdef HAS_DOS_H
64 # include <dos.h>
65 #endif
66
67 #ifdef HAS_PROCESS_H
68 # include <process.h>
69 #endif
70
71 /* fidoconf */
72 #include <fidoconf/fidoconf.h>
73 #include <fidoconf/common.h>
74 #include <huskylib/log.h>
75 #include <huskylib/dirlayer.h>
76 #include <huskylib/xstr.h>
77 #include <fidoconf/afixcmd.h>
78 #include <huskylib/recode.h>
79 #include <huskylib/crc.h>
80 #include <areafix/query.h>
81 #include <areafix/areafix.h>
82
83 #if defined(A_HIDDEN) && !defined(_A_HIDDEN)
84 # define _A_HIDDEN A_HIDDEN
85 #endif
86
87 /* htick */
88 #include <fcommon.h>
89 #include <global.h>
90 #include <toss.h>
91 #include <htickafix.h>
92 #include <add_desc.h>
93 #include <seenby.h>
94 #include <filecase.h>
95 #include "hatch.h"
96 #include "report.h"
97
98 char *versionStr;
99
100 /* tic keywords calculated crc (CCITT-16, polynom 0x1021) */
101
102 #define CRC_CREATED 0xACDA /*0x4EC6 */
103 #define CRC_FILE 0x9AF9 /*0x1A66 */
104 #define CRC_ALTFILE 0x02B3 /* "ALTFILE" */
105 #define CRC_AREADESC 0xD824 /*0xB621 */
106 #define CRC_DESC 0x717B /*0xECBD */
107 #define CRC_AREA 0x825A /*0x825A */
108 #define CRC_CRC 0x5487 /*0x5487 */
109 #define CRC_REPLACES 0xCE24 /*0xCF01 */
110 #define CRC_ORIGIN 0xE52A /*0xFCDC */
111 #define CRC_FROM 0xFD30 /*0x1293 */
112 #define CRC_TO 0x7B50 /*0x7B50 */
113 #define CRC_PATH 0x5411 /*0x5411 */
114 #define CRC_SEENBY 0xF84C /*0xC3D4 */
115 #define CRC_PW 0x24AD /*0x24AD */
116 #define CRC_SIZE 0x94CE /*0x5593 */
117 #define CRC_DATE 0x54EA /*0xD4BD */
118 #define CRC_DESTINATION 0x6F36 /*0xA9D1 */
119 #define CRC_MAGIC 0x7FF4 /*0xD858 */
120 #define CRC_LDESC 0xEB38 /*0x5394 */
121
122 /* Write netmail message into areaname or first netmail area (if areaname is NULL pointer)
123 */
writeNetmail(s_message * msg,char * areaName)124 void writeNetmail( s_message * msg, char *areaName )
125 {
126 HAREA netmail;
127 HMSG msgHandle;
128 UINT len = msg->textLength;
129 char *bodyStart; /* msg-body without kludgelines start */
130 char *ctrlBuf; /* Kludgelines */
131 XMSG msgHeader;
132 s_area *nmarea;
133
134 if( ( msg == NULL ) )
135 {
136 w_log( LL_ERROR,
137 __FILE__
138 ":%i: Parameter is a NULL pointer: writeNetmail(NULL,areaname). This is a bug, please report it to developers.",
139 __LINE__ );
140 return;
141 }
142
143 if( !config->netMailAreas )
144 {
145 w_log( LL_CRIT, "Netmail areas not defined, message dropped! Please check config." );
146 return;
147 }
148 if( !areaName || ( nmarea = getNetMailArea( config, areaName ) ) == NULL )
149 nmarea = &( config->netMailAreas[0] );
150
151 netmail = MsgOpenArea( ( UCHAR * ) nmarea->fileName, MSGAREA_CRIFNEC, ( word ) nmarea->msgbType );
152
153 if( netmail != NULL )
154 {
155 msgHandle = MsgOpenMsg( netmail, MOPEN_CREATE, 0 );
156
157 if( msgHandle != NULL )
158 {
159 if( ( !config->recodeMsgBase ) && ( config->outtab != NULL ) )
160 {
161 recodeToTransportCharset( ( char * )msg->subjectLine );
162 recodeToTransportCharset( ( char * )msg->fromUserName );
163 recodeToTransportCharset( ( char * )msg->toUserName );
164 recodeToTransportCharset( ( char * )msg->text );
165 }
166
167 msgHeader = createXMSG( config, msg, NULL, MSGLOCAL, NULL );
168 /* Create CtrlBuf for SMAPI */
169 {
170 byte *bb; /* Prevent GCC warning "dereferencing type-punned pointer will break strict-aliasing rules" */
171
172 ctrlBuf = ( char * )CopyToControlBuf( msg->text, &bb, &len );
173 bodyStart = bb;
174 }
175
176 /* write message */
177 MsgWriteMsg( msgHandle, 0, &msgHeader, ( UCHAR * ) bodyStart, len, len, strlen( ctrlBuf ) + 1,
178 ( UCHAR * ) ctrlBuf );
179 free( ctrlBuf );
180 MsgCloseMsg( msgHandle );
181
182 w_log( LL_POSTING, "Wrote Netmail to: %u:%u/%u.%u",
183 msg->destAddr.zone, msg->destAddr.net, msg->destAddr.node, msg->destAddr.point );
184 }
185 else
186 {
187 w_log( LL_ERROR, "Could not write message to %s", areaName );
188 } /* endif */
189
190 MsgCloseArea( netmail );
191 }
192 else
193 {
194 /* printf("%u\n", msgapierr); */
195 w_log( LL_ERROR, "Could not open netmail area %s", areaName );
196 } /* endif */
197 }
198
199 /* Write (create) TIC-file
200 * Return 0 if error, 1 if success
201 */
writeTic(char * ticfile,s_ticfile * tic)202 int writeTic( char *ticfile, s_ticfile * tic )
203 {
204 FILE *tichandle;
205 unsigned int i;
206 char *p;
207 s_area *filearea = NULL;
208
209 if( ( ticfile == NULL ) || ( tic == NULL ) )
210 {
211 w_log( LL_ERROR,
212 __FILE__
213 ":%i: Parameter is a NULL pointer: writeTic(%s%s%s,%s). This is a bug, please report it to developers.",
214 __LINE__, ticfile ? "\"" : "", ticfile ? ticfile : "NULL", ticfile ? "\"" : "",
215 tic ? "tic" : "NULL" );
216 return 0;
217 }
218 tichandle = fopen( ticfile, "wb" );
219 if( !tichandle )
220 {
221 w_log( LL_ERROR, "Unable to open TIC file \"%s\": %s!!!\n", ticfile, strerror( errno ) );
222 return 0;
223 }
224
225 fprintf( tichandle, "Created by HTick, written by Gabriel Plutzar\r\n" );
226 fprintf( tichandle, "File %s\r\n", tic->file );
227 fprintf( tichandle, "Area %s\r\n", tic->area );
228
229 filearea = getFileArea( tic->area );
230
231 if( !tic->areadesc && filearea && filearea->description )
232 {
233 tic->areadesc = sstrdup( filearea->description );
234 if( config->outtab )
235 {
236 recodeToTransportCharset( tic->areadesc );
237 }
238 }
239 if( tic->areadesc )
240 fprintf( tichandle, "Areadesc %s\r\n", tic->areadesc );
241
242 for( i = 0; i < tic->anzdesc; i++ )
243 fprintf( tichandle, "Desc %s\r\n", tic->desc[i] );
244
245 for( i = 0; i < tic->anzldesc; i++ )
246 {
247 while( ( p = strchr( tic->ldesc[i], 26 ) ) != NULL )
248 *p = ' ';
249 fprintf( tichandle, "LDesc %s\r\n", tic->ldesc[i] );
250 }
251
252 if( tic->replaces )
253 fprintf( tichandle, "Replaces %s\r\n", tic->replaces );
254 if( tic->from.zone != 0 )
255 fprintf( tichandle, "From %s\r\n", aka2str( tic->from ) );
256 if( tic->to.zone != 0 )
257 fprintf( tichandle, "To %s\r\n", aka2str( tic->to ) );
258 if( tic->origin.zone != 0 )
259 fprintf( tichandle, "Origin %s\r\n", aka2str( tic->origin ) );
260 if( tic->size >= 0 )
261 fprintf( tichandle, "Size %u\r\n", tic->size );
262 if( tic->date != 0 )
263 fprintf( tichandle, "Date %lu\r\n", tic->date );
264 if( tic->crc_is_present || tic->crc ) /* FIXME: Look through all code to check up simultaneous change of a tic.crc and a tic.tic->crc */
265 fprintf( tichandle, "Crc %08lX\r\n", tic->crc );
266
267 for( i = 0; i < tic->anzpath; i++ )
268 fprintf( tichandle, "Path %s\r\n", tic->path[i] );
269
270 for( i = 0; i < tic->anzseenby; i++ )
271 fprintf( tichandle, "Seenby %s\r\n", aka2str( tic->seenby[i] ) );
272
273 if( tic->password )
274 fprintf( tichandle, "Pw %s\r\n", tic->password );
275
276 fclose( tichandle );
277 return 1;
278 } /* writeTic() */
279
280 /* Free memory allocated in structure s_ticfile *tic
281 */
disposeTic(s_ticfile * tic)282 void disposeTic( s_ticfile * tic )
283 {
284 unsigned int i;
285
286 if( ( tic == NULL ) )
287 {
288 w_log( LL_ERROR,
289 __FILE__
290 ":%i: Parameter is a NULL pointer: disposeTic(NULL). This is a bug, please report it to developers.",
291 __LINE__ );
292 return;
293 }
294 nfree( tic->seenby );
295 nfree( tic->file );
296 nfree(tic->altfile);
297 nfree( tic->area );
298 nfree( tic->areadesc );
299 nfree( tic->replaces );
300 nfree( tic->password );
301
302 for( i = 0; i < tic->anzpath; i++ )
303 nfree( tic->path[i] );
304 nfree( tic->path );
305
306 for( i = 0; i < tic->anzdesc; i++ )
307 nfree( tic->desc[i] );
308 nfree( tic->desc );
309
310 for( i = 0; i < tic->anzldesc; i++ )
311 nfree( tic->ldesc[i] );
312 nfree( tic->ldesc );
313 } /* disposeTic() */
314
315 /* Check TIC file validity
316 * Return: 0 if TIC is valid,
317 * negative integer if error found in function arguments,
318 * positive integer if information in TIC is bad (the value is the number of errors)
319 */
checkTic(const char * ticfilename,const s_ticfile * tic)320 static int checkTic( const char *ticfilename, const s_ticfile * tic )
321 {
322 int nRet = 0;
323
324 if( ( ticfilename == NULL ) || ( tic == NULL ) )
325 {
326 w_log( LL_ERROR,
327 __FILE__
328 ":%i: Parameter is a NULL pointer: checkTic(%s%s%s,%s). This is a bug, please report it to developers.",
329 __LINE__, ticfilename ? "\"" : "", ticfilename ? ticfilename : "NULL",
330 ticfilename ? "\"" : "", tic ? "tic" : "NULL" );
331 return -1;
332 }
333 if( !tic->file )
334 {
335 w_log( LL_ERR, "File name is missing in TIC \"%s\" but required by FSC-87", ticfilename );
336 nRet++;
337 }
338
339 if( !tic->area )
340 {
341 w_log( LL_ERR, "Filearea name is missing in TIC \"%s\" but required by FSC-87", ticfilename );
342 nRet++;
343 }
344
345 if( !tic->crc_is_present )
346 {
347 w_log( LL_SECURITY, "CRC is missing in TIC \"%s\" but required by FSC-87", ticfilename );
348 }
349
350 if( tic->size < 0 )
351 {
352 w_log( LL_ALERT, "There is no file size in TIC %s, FSC-87 says: \"SHOULD be required\"",
353 ticfilename );
354 }
355
356 if( ( !tic->crc ) && ( tic->size > 0 ) )
357 {
358 w_log( LL_ERR,
359 "The size is not zero but CRC32 equals zero in TIC %s, it is impossible and this ticket file is wrong.",
360 ticfilename );
361 nRet++;
362 }
363
364 if( ( !tic->size ) && ( tic->crc_is_present ) )
365 {
366 w_log( LL_ERR,
367 "The size equals zero but CRC32 is not zero in TIC %s, it is impossible and this ticket file is wrong.",
368 ticfilename );
369 nRet++;
370 }
371
372 if( !tic->to.zone && !tic->to.net && !tic->to.node )
373 {
374 w_log( LL_SECURITY, "'To' address is missing in TIC \"%s\"", ticfilename );
375 }
376 else if( !tic->to.zone || !tic->to.net )
377 {
378 w_log( LL_ERR, "'To' address (%s) is illegal in TIC \"%s\"", aka2str( tic->to ), ticfilename );
379 nRet++;
380 }
381
382 if( !tic->from.zone && !tic->from.net && !tic->from.node )
383 {
384 w_log( LL_ERR, "'From' address is missing in TIC \"%s\", required by FSC-87", ticfilename );
385 nRet++;
386 }
387 else if( !tic->from.zone || !tic->from.net )
388 {
389 w_log( LL_ERR, "Zone or net is missing in the 'From' address in TIC \"%s\"", ticfilename );
390 nRet++;
391 }
392
393 if( !tic->origin.zone && !tic->origin.net && !tic->origin.node )
394 {
395 w_log( LL_ERR, "Originating address is missing in TIC \"%s\", required by FSC-87",
396 ticfilename );
397 /* nRet++; */
398 }
399 else if( !tic->origin.zone || !tic->origin.node )
400 {
401 w_log( LL_ERR, "Zone or node is missing in the originating address in TIC \"%s\"", ticfilename );
402 /* nRet++; */
403 }
404
405 if( !tic->path )
406 {
407 w_log( LL_ALERT, "PATH lines are missing in TIC \"%s\", required by FSC-87", ticfilename );
408 }
409
410 if( !tic->seenby )
411 {
412 w_log( LL_ALERT, "SEENBY lines are missing in TIC \"%s\", required by FSC-87", ticfilename );
413 }
414
415 if( !tic->password )
416 { /* Mandatory field (FSC-87) */
417 w_log( LL_SECURITY, "Password is missing in TIC \"%s\", required by FSC-87", ticfilename );
418 }
419
420 return nRet;
421 } /* checkTic */
422
423
424 /* Read TIC file and store values into 2nd parameter.
425 * Return 1 if success, 2 if bad data in tic, and 0 if file or parameter error.
426 * Clean 2nd parameter before processing if not error.
427 */
parseTic(char * ticfile,s_ticfile * tic)428 enum parseTic_result parseTic( char *ticfile, s_ticfile * tic )
429 {
430 FILE *tichandle;
431 char *line, *token, *param, *linecut = "", *emptyline = "";
432 s_link *ticSourceLink = NULL;
433 UINT16 key;
434 hs_addr Aka;
435 int rc = parseTic_success;
436
437 if( ( ticfile == NULL ) || ( tic == NULL ) )
438 {
439 w_log( LL_ERROR,
440 __FILE__
441 ":%i: Parameter is a NULL pointer: parseTic(%s%s%s,%s). This is a bug, please report it to developers.",
442 __LINE__, ticfile ? "\"" : "", ticfile ? ticfile : "NULL", ticfile ? "\"" : "",
443 tic ? "tic" : "NULL" );
444 return parseTic_error;
445 }
446 memset( tic, '\0', sizeof( s_ticfile ) );
447 tic->size = -1; /* For check existing a token "size" in TIC file */
448
449 #ifndef HAS_sopen
450 tichandle = fopen( ticfile, "r" );
451 #else
452 {
453 int fh = 0;
454
455 /* insure that ticfile won't be removed while parsing */
456 # if defined (__UNIX__) || defined (__DJGPP__)
457 fh = sopen( ticfile, O_RDWR | O_BINARY, SH_DENYNO, S_IWRITE | S_IREAD );
458 # else
459 fh = sopen( ticfile, O_RDWR | O_BINARY, SH_DENYRW );
460 # endif
461 if( fh < 0 )
462 {
463 w_log( LL_ERROR, "Can't open '%s': %s (sopen())", ticfile, strerror( errno ) );
464 return parseTic_error;
465 }
466 tichandle = fdopen( fh, "r" );
467 }
468 #endif
469
470 if( !tichandle )
471 {
472 w_log( LL_ERROR, "Can't open '%s': %s", ticfile, strerror( errno ) );
473 return parseTic_error;
474 }
475
476 while( ( line = readLine( tichandle ) ) != NULL )
477 {
478 line = trimLine( line );
479
480 if( *line == 0 || *line == 10 || *line == 13 || *line == ';' || *line == '#' )
481 continue;
482
483 if( config->MaxTicLineLength )
484 {
485 linecut = ( char * )smalloc( config->MaxTicLineLength + 1 );
486 strncpy( linecut, line, config->MaxTicLineLength );
487 linecut[config->MaxTicLineLength] = 0;
488 token = strtok( linecut, " \t" );
489 }
490 else
491 token = strtok( line, " \t" );
492
493 if( token )
494 {
495 key = strcrc16( strUpper( token ), 0 );
496 /* calculate crc16 of tic */
497 w_log( LL_DEBUGz, "#define CRC_%-12s 0x%X;", strUpper( token ), key );
498 param = stripLeadingChars( strtok( NULL, "\0" ), "\t" );
499 if( !param )
500 {
501 switch ( key )
502 {
503 case CRC_DESC:
504 case CRC_LDESC:
505 param = emptyline;
506 break;
507 case CRC_SIZE:
508 w_log( LL_ERR, "Wrong TIC \"%s\": \"Size\" without value!", ticfile );
509 tic->size = -1;
510 rc = parseTic_bad;
511 break;
512 default:
513 continue;
514 }
515 }
516 switch ( key )
517 {
518 case CRC_CREATED:
519 case CRC_MAGIC:
520 break;
521 case CRC_FILE:
522 tic->file = sstrdup( param );
523 break;
524 case CRC_ALTFILE:
525 tic->altfile = sstrdup(param); /* just for reports */
526 break;
527 case CRC_AREADESC:
528 tic->areadesc = sstrdup( param );
529 break;
530 case CRC_AREA:
531 tic->area = sstrdup( param );
532 break;
533 case CRC_CRC:
534 tic->crc = strtoul( param, NULL, 16 );
535 tic->crc_is_present = 1;
536 break;
537 case CRC_SIZE:
538 if( param[0] == '-' )
539 {
540 w_log( LL_ERR, "Wrong TIC \"%s\": negative size (\"%s\")!", ticfile, param );
541 rc = parseTic_bad;
542 }
543 else
544 {
545 tic->size = tic->size = atoi( param );
546 if( ( !tic->size ) && ( !strcmp( param, "0" ) ) )
547 {
548 w_log( LL_ERR, "Wrong TIC \"%s\": value of size is \"%s\"! "
549 "(May be pozitive integer or one zero", ticfile, param );
550 rc = parseTic_bad;
551 }
552 }
553 break;
554 case CRC_DATE:
555 tic->date = atoi( param );
556 break;
557 case CRC_REPLACES:
558 if( *param == '*' )
559 {
560 w_log( LL_TIC, "TIC %s: Illegal value: 'REPLACES %s', ignored", ticfile, param );
561 break;
562 }
563 tic->replaces = sstrdup( param );
564 break;
565 case CRC_PW:
566 tic->password = sstrdup( param );
567 break;
568 case CRC_FROM:
569 parseFtnAddrZS( param, &tic->from );
570 ticSourceLink = getLinkFromAddr( config, tic->from );
571 break;
572 case CRC_ORIGIN:
573 parseFtnAddrZS( param, &tic->origin );
574 break;
575 case CRC_TO:
576 parseFtnAddrZS( param, &tic->to );
577 if( !tic->to.zone || !tic->to.net )
578 {
579 w_log( LL_ERR, "No zone or net in the 'To' address (%s) in TIC %s", param, ticfile );
580 rc = parseTic_bad;
581 }
582 break;
583 case CRC_DESTINATION:
584 if( ticSourceLink && !ticSourceLink->FileFixFSC87Subset )
585 parseFtnAddrZS( param, &tic->to );
586 break;
587 case CRC_DESC:
588 tic->desc = srealloc( tic->desc, ( tic->anzdesc + 1 ) * sizeof( *tic->desc ) );
589 tic->desc[tic->anzdesc] = sstrdup( param );
590 tic->anzdesc++;
591 break;
592 case CRC_LDESC:
593 tic->ldesc = srealloc( tic->ldesc, ( tic->anzldesc + 1 ) * sizeof( *tic->ldesc ) );
594 tic->ldesc[tic->anzldesc] = sstrdup( param );
595 tic->anzldesc++;
596 break;
597 case CRC_SEENBY:
598 memset( &Aka, 0, sizeof( Aka ) );
599 if( parseFtnAddrZS( param, &Aka ) & FTNADDR_ERROR )
600 {
601 w_log( LL_TIC, "TIC %s: Illegal value: 'Seenby %s', ignored", ticfile, param );
602 }
603 else
604 {
605 seenbyAdd( &tic->seenby, &tic->anzseenby, &Aka );
606 }
607 break;
608 case CRC_PATH:
609 tic->path = srealloc( tic->path, ( tic->anzpath + 1 ) * sizeof( *tic->path ) );
610 tic->path[tic->anzpath] = sstrdup( param );
611 tic->anzpath++;
612 break;
613 default:
614 if( ticSourceLink && !ticSourceLink->FileFixFSC87Subset )
615 {
616 w_log( LL_WARNING, "Unknown Keyword %s in Tic File", token );
617 rc = parseTic_bad;
618 }
619 } /* switch */
620 } /* endif */
621 if( config->MaxTicLineLength )
622 nfree( linecut );
623 nfree( line );
624 } /* endwhile */
625
626 fclose( tichandle );
627
628 if( !tic->anzdesc )
629 {
630 tic->desc = srealloc( tic->desc, sizeof( *tic->desc ) );
631 tic->desc[0] = sstrdup( "no desc" );
632 tic->anzdesc = 1;
633 }
634
635 return rc;
636 } /* parseTic */
637
638 /* Save ticket file into filearea-specific directory
639 */
doSaveTic(char * ticfile,s_ticfile * tic,s_area * filearea)640 void doSaveTic( char *ticfile, s_ticfile * tic, s_area * filearea )
641 {
642 unsigned int i;
643 s_savetic *savetic;
644
645 if( ( tic == NULL ) || ( filearea == NULL ) )
646 {
647 w_log( LL_ERROR,
648 __FILE__
649 ":%i: Parameter is a NULL pointer: doSaveTic(%s%s%s,%s,%s). This is a bug, please report it to developers.",
650 __LINE__, ticfile ? "\"" : "", ticfile ? ticfile : "", ticfile ? "\"" : "",
651 tic ? "tic" : "NULL", filearea ? "filearea" : "NULL" );
652 return;
653 }
654
655 for( i = 0; i < config->saveTicCount; i++ )
656 {
657 savetic = &( config->saveTic[i] );
658 if( patimat( tic->area, savetic->fileAreaNameMask ) == 1 )
659 {
660 char *ticFname = NULL;
661 char *filename = NULL;
662
663 if( ticfile )
664 {
665 ticFname = GetFilenameFromPathname( ticfile );
666 w_log( LL_FILENAME, "Saving Tic-File \"%s\" to \"%s\"", ticFname, savetic->pathName );
667 xscatprintf( &filename, "%s%s", savetic->pathName, ticFname );
668 if( copy_file( ticfile, filename, 1 ) != 0 )
669 { /* overwrite existing file if not same */
670 w_log( LL_ERROR, "File \"%s\" not found or not moveable", ticfile );
671 }
672 }
673 else
674 {
675 filename = makeUniqueDosFileName( savetic->pathName, "tic", config );
676 w_log( LL_FILENAME, "Saving Tic-File \"%s\" to \"%s\"", GetFilenameFromPathname( filename ),
677 savetic->pathName );
678 writeTic( filename, tic );
679 }
680 nfree( filename );
681
682 if( filearea &&
683 filearea->msgbType != MSGTYPE_PASSTHROUGH && !filearea->sendorig && savetic->fileAction )
684 {
685 char *from = NULL, *to = NULL;
686
687 xstrscat( &from, filearea->fileName, tic->file, NULL );
688 xstrscat( &to, savetic->pathName, tic->file, NULL );
689 if( savetic->fileAction == 1 )
690 copy_file( from, to, 1 ); /* overwrite existing file if not same */
691 if( savetic->fileAction == 2 )
692 link_file( from, to );
693 nfree( from );
694 nfree( to );
695 }
696 break;
697 };
698
699 };
700 return;
701 } /* doSaveTic */
702
703
704 /*
705 * create alternative filename for ticked file
706 * - add counter 01 up to 99
707 *
708 * requires:
709 * - path of destination directory
710 * - name of ticked file
711 *
712 * returns:
713 * - string pointer (allocated buffer) on success
714 * - NULL on any problem
715 */
716
altFilename(char * path,char * name)717 char *altFilename(char *path, char *name)
718 {
719 char *altName = NULL; /* return value */
720 char *tempName = NULL; /* temporary name */
721 char *tempFilepath = NULL; /* temporary filepath */
722 char *modStr;
723 char *remStr = NULL;
724 unsigned int n = 1;
725 size_t size;
726
727 /* sanity checks */
728 if ((path == NULL) || (name == NULL)) return altName;
729
730 /* allocate buffers */
731 size = strlen(name) + 4; /* + dot + 2 digits + \0 */
732 tempName = smalloc(size);
733 size += strlen(path);
734 tempFilepath = smalloc(size);
735
736
737 /* prepare temp. name */
738 strcpy(tempName, name);
739 modStr = strchr(tempName, '.'); /* find first dot */
740 if (modStr == NULL) /* no dot found */
741 {
742 /* find end of string */
743 modStr = tempName;
744 while (modStr[0] != 0) modStr++;
745
746 modStr[0] = '.'; /* add dot */
747 }
748 else /* dot found */
749 {
750 /* get pointer to remaining part in original string */
751 remStr = strchr(name, '.');
752 }
753 modStr++; /* skip dot */
754 modStr[0] = 0; /* end string */
755
756 if (isDOSLikeName(name)) /* DOS filename */
757 {
758 if (remStr) /* more chars follow */
759 {
760 remStr++; /* skip dot */
761 modStr[0] = remStr[0]; /* copy first char behind dot */
762 modStr++; /* and skip it */
763 remStr = NULL; /* don't care about the remaining chars */
764 }
765 }
766
767 /* check alternative names */
768 while (n < 99)
769 {
770 /* complete temp. filename */
771 sprintf(modStr, "%.2d", n); /* add counter */
772 if (remStr) strcat(modStr, remStr); /* add remaining part */
773
774 strcpy(tempFilepath, path); /* build full filepath */
775 strcat(tempFilepath, tempName);
776
777 if (!fexist(tempFilepath)) break; /* unused filename */
778 else n++; /* try next one */
779 }
780
781 if (n <= 99) altName = tempName; /* found alternative */
782 else nfree(tempName); /* found none */
783 nfree(tempFilepath);
784
785 return altName;
786 }
787
788
789 /* Send a file "filename" to all subscribers of fileecho.
790 * Return: 0 if success, positive integer if error, negative integer if illegal call
791 */
sendToLinks(int isToss,s_area * filearea,s_ticfile * tic,const char * filename)792 int sendToLinks( int isToss, s_area * filearea, s_ticfile * tic, const char *filename )
793 /*
794 * isToss == 1 - tossing
795 * isToss == 0 - hatching
796 */
797 {
798 unsigned int i, z;
799 char descr_file_name[256], newtickedfile[256], fileareapath[256];
800 char timestr[40];
801 time_t acttime;
802 hs_addr *old_seenby = NULL;
803 hs_addr old_from, old_to;
804 int old_anzseenby = 0;
805 int readAccess;
806 int cmdexit;
807 char *comm;
808 char *p;
809 unsigned int minLinkCount;
810
811 if( ( filearea == NULL ) || ( tic == NULL ) || ( filename == NULL ) )
812 {
813 w_log( LL_ERROR,
814 __FILE__
815 ":%i: Parameter is a NULL pointer: sendToLinks(%i,%s,%s,%s%s%s). This is a bug, please report it to developers.",
816 __LINE__, isToss, filearea ? "filearea" : "NULL", tic ? "tic" : "NULL",
817 filename ? "\"" : "", filename ? filename : "NULL", filename ? "\"" : "" );
818 return TIC_UnknownError;
819 }
820
821 if( isToss == 1 )
822 minLinkCount = 2; /* uplink and downlink */
823 else
824 minLinkCount = 1; /* only downlink */
825
826 if( !fexist( filename ) )
827 {
828 /* origin file does not exist */
829 w_log( LL_ERROR, "File \"%s\" not found, nothing to send to links", filename );
830 return TIC_NotRecvd;
831 }
832
833 if( filearea->msgbType != MSGTYPE_PASSTHROUGH )
834 strcpy( fileareapath, filearea->fileName );
835 else
836 strcpy( fileareapath, config->passFileAreaDir );
837 p = strrchr( fileareapath, PATH_DELIM );
838 if( p )
839 strLower( p + 1 );
840
841 _createDirectoryTree( fileareapath );
842
843 if( isToss == 1 && tic->replaces != NULL && filearea->msgbType != MSGTYPE_PASSTHROUGH
844 && !filearea->noreplace )
845 {
846 /* Delete old file[s] */
847 int num_files;
848 char *repl;
849
850 repl = strrchr( tic->replaces, PATH_DELIM );
851 if( repl == NULL )
852 repl = tic->replaces;
853 else
854 repl++;
855 num_files = removeFileMask( fileareapath, repl );
856 if( num_files > 0 )
857 {
858 w_log( LL_DEL, "%d file[s] with filemask %s are removed", num_files, repl );
859 }
860 }
861
862 strcpy( newtickedfile, fileareapath );
863 strcat( newtickedfile, MakeProperCase( tic->file ) );
864
865 /* check for duplicates in the filearea */
866 if (filearea->msgbType != MSGTYPE_PASSTHROUGH && fexist(newtickedfile))
867 {
868 if (filearea->rename) /* rename new file */
869 {
870 comm = altFilename(&fileareapath[0], tic->file);
871 if (comm != NULL) /* found alternative name */
872 {
873 strcpy(newtickedfile, fileareapath);
874 strcat(newtickedfile, comm);
875 tic->altfile = comm;
876 w_log('6',"Created alternative name %s for file %s.", comm, tic->file);
877 }
878 else /* namespace exceeded or error */
879 {
880 w_log(LL_ERROR,"Couldn't create alternative name for file %s in filearea %s.", tic->file, tic->area);
881 return(TIC_NotOpen);
882 }
883 }
884 else if (filearea->noreplace) /* don't overwrite old file */
885 {
886 w_log(LL_ERROR,"File %s in filearea %s already exists. Can't replace it", tic->file, tic->area);
887 return(TIC_NotOpen);
888 }
889 }
890
891 if( isToss == 1 )
892 {
893 if (!filearea->sendorig && tic->altfile == NULL)
894 {
895 /* overwrite existing file if not same */
896 if( move_file( filename, newtickedfile, 1 ) != 0 )
897 {
898 w_log( LL_ERROR, "Can't copy file %s to %s: %s",
899 filename, newtickedfile, strerror( errno ) );
900 return TIC_NotOpen;
901 }
902 else
903 {
904 w_log( LL_CREAT, "Moved %s to %s", filename, newtickedfile );
905 }
906 }
907 else
908 {
909 /* overwrite existing file if not same */
910 if( copy_file( filename, newtickedfile, 1 ) != 0 )
911 {
912 w_log( LL_ERROR, "Can't copy file %s to %s: %s",
913 filename, newtickedfile, strerror( errno ) );
914 return TIC_NotOpen;
915 }
916 else
917 {
918 w_log( LL_CREAT, "Put %s to %s", filename, newtickedfile );
919 }
920 strcpy( newtickedfile, config->passFileAreaDir );
921 strcat( newtickedfile, MakeProperCase( tic->file ) );
922 /* overwrite existing file if not same */
923 if( move_file( filename, newtickedfile, 1 ) != 0 )
924 {
925 w_log( LL_ERROR, "Can't move file %s to %s: %s",
926 filename, newtickedfile, strerror( errno ) );
927 return TIC_NotOpen;
928 }
929 else
930 {
931 w_log( LL_CREAT, "Moved %s to %s", filename, newtickedfile );
932 }
933 }
934 }
935 else if( strcasecmp( filename, newtickedfile ) != 0 )
936 {
937 /* overwrite existing file if not same */
938 if( copy_file( filename, newtickedfile, 1 ) != 0 )
939 {
940 w_log( LL_ERROR, "Can't copy file %s to %s: %s", filename, newtickedfile, strerror( errno ) );
941 return TIC_NotOpen;
942 }
943 else
944 {
945 w_log( LL_CREAT, "Put %s to %s", filename, newtickedfile );
946 }
947 if (filearea->sendorig || tic->altfile)
948 {
949 strcpy( newtickedfile, config->passFileAreaDir );
950 strcat( newtickedfile, MakeProperCase( tic->file ) );
951 if( copy_file( filename, newtickedfile, 1 ) != 0 )
952 {
953 w_log( LL_ERROR, "Can't copy file \"%s\" to \"%s\": %s",
954 filename, newtickedfile, strerror( errno ) );
955 return TIC_NotOpen;
956 }
957 else
958 {
959 w_log( LL_CREAT, "Put \"%s\" to \"%s\"", filename, newtickedfile );
960 }
961 }
962 }
963
964 if( tic->anzldesc == 0 && config->fDescNameCount && !filearea->nodiz && isToss )
965 GetDescFormDizFile( newtickedfile, tic );
966
967 if( config->announceSpool )
968 doSaveTic4Report( tic );
969
970 if( filearea->msgbType != MSGTYPE_PASSTHROUGH )
971 {
972 strcpy( descr_file_name, filearea->fileName );
973 strcat( descr_file_name, config->fileDescription );
974 adaptcase( descr_file_name );
975 if (tic->altfile) comm = tic->altfile; /* use alternative name */
976 else comm = tic->file; /* use original name */
977 removeDesc( descr_file_name, comm );
978 if( tic->anzldesc > 0 )
979 add_description( descr_file_name, comm, tic->ldesc, tic->anzldesc );
980 else
981 add_description( descr_file_name, comm, tic->desc, tic->anzdesc );
982 }
983
984 if( filearea->downlinkCount >= minLinkCount )
985 {
986 /* Adding path & seenbys */
987 time( &acttime );
988 strcpy( timestr, asctime( gmtime( &acttime ) ) );
989 timestr[strlen( timestr ) - 1] = 0;
990 if( timestr[8] == ' ' )
991 timestr[8] = '0';
992
993 tic->path = srealloc( tic->path, ( tic->anzpath + 1 ) * sizeof( *tic->path ) );
994 tic->path[tic->anzpath] = NULL;
995 xscatprintf( &tic->path[tic->anzpath], "%s %lu %s UTC %s",
996 aka2str( *filearea->useAka ), ( unsigned long )time( NULL ), timestr, versionStr );
997 tic->anzpath++;
998 }
999
1000 if( isToss == 1 )
1001 {
1002 /* Save seenby structure */
1003 old_seenby = smalloc( tic->anzseenby * sizeof( hs_addr ) );
1004 memcpy( old_seenby, tic->seenby, tic->anzseenby * sizeof( hs_addr ) );
1005 old_anzseenby = tic->anzseenby;
1006 memcpy( &old_from, &tic->from, sizeof( hs_addr ) );
1007 memcpy( &old_to, &tic->to, sizeof( hs_addr ) );
1008 }
1009 else
1010 {
1011 memset( &old_from, 0, sizeof( hs_addr ) );
1012 memset( &old_to, 0, sizeof( hs_addr ) );
1013 }
1014
1015 if( tic->anzseenby > 0 )
1016 {
1017 for( i = 0; i < filearea->downlinkCount; i++ )
1018 {
1019 s_link *downlink = filearea->downlinks[i]->link;
1020
1021 if( ( seenbyComp( tic->seenby, tic->anzseenby, downlink->hisAka ) ) &&
1022 ( e_readCheck( config, filearea, downlink ) == 0 ) )
1023 { /* if link is not in seen-by list & */
1024 /* if link can receive files from the filearea */
1025 /* Adding Downlink to Seen-By */
1026 /*
1027 * tic->seenby=srealloc(tic->seenby,(tic->anzseenby+1)*sizeof(hs_addr));
1028 * memcpy(&tic->seenby[tic->anzseenby],&downlink->hisAka,sizeof(hs_addr));
1029 * tic->anzseenby++;
1030 */
1031 seenbyAdd( &tic->seenby, &tic->anzseenby, &downlink->hisAka );
1032 }
1033 }
1034 }
1035 else
1036 w_log( LL_WARN, "Seen-By list is empty in TIC file for \"%s\" (wrong TIC)!",
1037 tic->file ? tic->file : "" );
1038
1039 /* (dmitry) FixMe: Put correct AKA here if To: is missing in tic */
1040 if( isOurAka( config, tic->to ) && seenbyComp( tic->seenby, tic->anzseenby, tic->to ) )
1041 seenbyAdd( &tic->seenby, &tic->anzseenby, &tic->to );
1042 else
1043 seenbyAdd( &tic->seenby, &tic->anzseenby, filearea->useAka );
1044
1045 seenbySort( tic->seenby, tic->anzseenby );
1046
1047 /* Checking to whom I shall forward */
1048 for( i = 0; i < filearea->downlinkCount; i++ )
1049 {
1050 s_link *downlink = filearea->downlinks[i]->link;
1051
1052 if( addrComp( old_from, downlink->hisAka ) != 0 &&
1053 addrComp( old_to, downlink->hisAka ) != 0 &&
1054 addrComp( tic->origin, downlink->hisAka ) != 0 )
1055 {
1056 /* Forward file to */
1057
1058 readAccess = e_readCheck( config, filearea, downlink );
1059 switch ( readAccess )
1060 {
1061 case 0:
1062 break;
1063 case 5:
1064 w_log( LL_FROUTE, "Link %s is paused", aka2str( downlink->hisAka ) );
1065 break;
1066 case 4:
1067 w_log( LL_FROUTE, "Link %s is not subscribed to File Area %s",
1068 aka2str( old_from ), tic->area );
1069 break;
1070 case 3:
1071 w_log( LL_FROUTE, "No export (or write only) to link %s", aka2str( downlink->hisAka ) );
1072 break;
1073 case 2:
1074 w_log( LL_FROUTE, "Link's %s level provides no access", aka2str( downlink->hisAka ) );
1075 break;
1076 case 1:
1077 w_log( LL_FROUTE, "The group the area %s belongs to is neither in PublicGroup nor in link's %s AccessGrp",
1078 filearea->areaName, aka2str( downlink->hisAka ) );
1079 break;
1080 }
1081
1082 if( readAccess == 0 )
1083 {
1084 if( isToss == 1 && seenbyComp( old_seenby, old_anzseenby, downlink->hisAka ) == 0 )
1085 {
1086 w_log( LL_FROUTE, "File %s was already seen by %s", tic->file, aka2str( downlink->hisAka ) );
1087 }
1088 else
1089 {
1090 PutFileOnLink( newtickedfile, tic, downlink );
1091 }
1092 } /* if readAccess == 0 */
1093 } /* Forward file */
1094 }
1095 /* execute external program */
1096 for( z = 0; z < config->execonfileCount; z++ )
1097 {
1098 if( stricmp( filearea->areaName, config->execonfile[z].filearea ) != 0 )
1099 continue;
1100 if( patimat( tic->file, config->execonfile[z].filename ) == 0 )
1101 continue;
1102 else
1103 {
1104 comm = ( char * )smalloc( strlen( config->execonfile[z].command ) + 1
1105 + ( filearea->msgbType !=
1106 MSGTYPE_PASSTHROUGH ? strlen( filearea->
1107 fileName ) : strlen( config->
1108 passFileAreaDir ) )
1109 + strlen( tic->file ) + 1 );
1110 if( comm == NULL )
1111 {
1112 w_log( LL_ERROR, "Exec failed - not enough memory" );
1113 continue;
1114 }
1115 sprintf( comm, "%s %s%s", config->execonfile[z].command,
1116 ( filearea->msgbType !=
1117 MSGTYPE_PASSTHROUGH ? filearea->fileName : config->passFileAreaDir ), tic->file );
1118 w_log( LL_EXEC, "Executing \"%s\"", comm );
1119 if( ( cmdexit = system( comm ) ) != 0 )
1120 {
1121 w_log( LL_ERROR, "Exec failed with exit code %d", cmdexit );
1122 }
1123 nfree( comm );
1124 }
1125 }
1126
1127 if( isToss == 1 )
1128 nfree( old_seenby );
1129 return ( TIC_OK );
1130 } /* sendToLinks */
1131
1132 #if !defined(__UNIX__)
1133
1134 /* FIXME: This code is nonportable and should therefore really be part
1135 of a porting library like huskylib or !!!
1136 */
1137
1138 # if defined(__NT__)
1139 /* we can't include windows.h for several reasons ... */
1140 # define GetFileAttributes GetFileAttributesA
1141 # endif
1142
1143
hidden(char * filename)1144 int hidden( char *filename )
1145 {
1146 # if (defined(__TURBOC__) && !defined(__OS2__)) || defined(__DJGPP__)
1147 unsigned fattrs;
1148
1149 _dos_getfileattr( filename, &fattrs );
1150 return fattrs & _A_HIDDEN;
1151 # elif defined(__NT__)
1152 unsigned fattrs;
1153
1154 fattrs = ( GetFileAttributes( filename ) & 0x2 ) ? _A_HIDDEN : 0;
1155 return fattrs & _A_HIDDEN;
1156 # elif defined (__OS2__)
1157 FILESTATUS3 fstat3;
1158 const char *p;
1159 char *q, *backslashified;
1160
1161 /* Under OS/2 users can also use "forward slashes" in filenames because
1162 * the OS/2 C libraries support this, but the OS/2 API itself does not
1163 * support this, and as we are calling an OS/2 API here we must first
1164 * transform slashes into backslashes */
1165
1166 backslashified = ( char * )smalloc( strlen( filename ) + 1 );
1167 for( p = filename, q = backslashified; *p; q++, p++ )
1168 {
1169 if( *p == '/' )
1170 *q = '\\';
1171 else
1172 *q = *p;
1173 }
1174 *q = '\0';
1175
1176 DosQueryPathInfo( ( PSZ ) backslashified, 1, &fstat3, sizeof( fstat3 ) );
1177
1178 free( backslashified );
1179
1180 return fstat3.attrFile & FILE_HIDDEN;
1181 # else
1182 # error "Don't know how to check for hidden files on this platform"
1183 return 0; /* well, we can't check if we don't know about the host */
1184 # endif
1185 }
1186 #endif
1187
1188 /*
1189 * Return: 0 if success (look for TIC_OK in htick/h/toss.h),
1190 * positive integer if error in TIC or file (see htick/h/toss.h),
1191 * negative integer if illegal call (look for TIC_UnknownError in htick/h/toss.h).
1192 */
processTic(char * ticfile,e_tossSecurity sec)1193 enum TIC_state processTic( char *ticfile, e_tossSecurity sec )
1194 {
1195 s_ticfile tic;
1196 size_t j;
1197 FILE *flohandle;
1198 husky_DIR *dir;
1199 char *file;
1200
1201 char tickedfile[256], linkfilepath[256];
1202 char dirname[256], *realfile, *findfile, *pos;
1203 char *newticfile;
1204 s_area *filearea;
1205 s_link *from_link, *to_link;
1206 int busy;
1207 struct stat stbuf;
1208 int writeAccess;
1209 int fileisfound = 0;
1210 int rc = 0;
1211 char *tic_origin;
1212
1213 w_log( LL_TIC, "Processing Tic-File %s", ticfile );
1214
1215 if( ( ticfile == NULL ) )
1216 {
1217 w_log( LL_ERROR,
1218 __FILE__
1219 ":%i: Parameter is a NULL pointer: processTic(%s,sec). This is a bug, please report it to developers.",
1220 __LINE__, ticfile ? "\"" : "", ticfile ? ticfile : "NULL", ticfile ? "\"" : "" );
1221 return TIC_UnknownError;
1222 }
1223
1224 if( ( j = strlen( ticfile ) ) > sizeof( tickedfile ) )
1225 {
1226 w_log( LL_ERROR, "File name too long: %u. Htick limit is %u characters.", j,
1227 sizeof( tickedfile ) );
1228 w_log( LL_TIC, "Ticket file \"%s\" is skipped", ticfile );
1229 return TIC_UnknownError;
1230 }
1231
1232 switch ( parseTic( ticfile, &tic ) )
1233 {
1234 case parseTic_error:
1235 return TIC_NotOpen;
1236 case parseTic_bad:
1237 return TIC_WrongTIC;
1238 }
1239
1240 {
1241 int r = checkTic( ticfile, &tic );
1242
1243 if( r > 0 )
1244 return TIC_WrongTIC;
1245 if( r < 0 )
1246 return TIC_UnknownError;
1247 }
1248
1249 if( tic.file && strpbrk( tic.file, "/\\:" ) )
1250 {
1251 w_log( LL_SECURITY, "Directory separator found in 'File' token: '%s' of %s TIC file", tic.file,
1252 ticfile );
1253 return TIC_Security;
1254 }
1255 if( tic.replaces && strpbrk( tic.replaces, "/\\:" ) )
1256 {
1257 w_log( LL_SECURITY, "Directory separator found in 'Replace' token: '%s' of %s TIC file",
1258 tic.replaces, ticfile );
1259 return TIC_Security;
1260 }
1261
1262 if( tic.size < 0 )
1263 w_log( LL_TIC, "File \"%s\": size: not specified, area: %s, from: %s, orig: %s",
1264 tic.file, tic.area, aka2str( tic.from ), tic_origin = aka2str5d( tic.origin ) );
1265 else
1266 w_log( LL_TIC, "File \"%s\": size: %ld, area: %s, from: %s, orig: %s",
1267 tic.file, tic.size, tic.area, aka2str( tic.from ), tic_origin =
1268 aka2str5d( tic.origin ) );
1269 nfree( tic_origin );
1270
1271 if( tic.to.zone != 0 )
1272 {
1273 if( !isOurAka( config, tic.to ) )
1274 {
1275 /* Forwarding tic and file to another link? */
1276 to_link = getLinkFromAddr( config, tic.to );
1277 if( ( to_link != NULL ) && ( to_link->forwardPkts != fOff ) )
1278 { /*FIXME: should use (new) forwardTICs! */
1279 /* Send the ticket and a file to the address in line "To" of ticket. ("Transit TICs routing") */
1280 if( !
1281 ( ( to_link->forwardPkts == fSecure ) && ( sec != secProtInbound )
1282 && ( sec != secLocalInbound ) ) )
1283 { /* Forwarding */
1284 w_log( LL_TIC, "Forward TIC \"%s\" (and file \"%s\") to %s", ticfile, tic.file,
1285 aka2str( tic.to ) );
1286 busy = 0;
1287 if( createOutboundFileNameAka( to_link,
1288 to_link->fileEchoFlavour, FLOFILE,
1289 SelectPackAka( to_link ) ) == 0 )
1290 {
1291 strcpy( linkfilepath, to_link->floFile );
1292 if( !busy )
1293 { /* FIXME: it is always not busy!!! */
1294 *( strrchr( linkfilepath, PATH_DELIM ) ) = 0;
1295 newticfile = makeUniqueDosFileName( linkfilepath, "tic", config );
1296 if( move_file( ticfile, newticfile, 0 ) == 0 )
1297 { /* don't overwrite existing file */
1298 strcpy( tickedfile, ticfile );
1299 *( strrchr( tickedfile, PATH_DELIM ) + 1 ) = 0;
1300 j = strlen( tickedfile );
1301 strcat( tickedfile, tic.file );
1302 adaptcase( tickedfile );
1303 strcpy( tic.file, tickedfile + j );
1304 flohandle = fopen( to_link->floFile, "a" );
1305 fprintf( flohandle, "^%s\n", tickedfile );
1306 fprintf( flohandle, "^%s\n", newticfile );
1307 fclose( flohandle );
1308 if( to_link->bsyFile )
1309 {
1310 remove( to_link->bsyFile );
1311 nfree( to_link->bsyFile );
1312 }
1313 nfree( to_link->floFile );
1314 }
1315 }
1316 }
1317 doSaveTic( ticfile, &tic, NULL );
1318 disposeTic( &tic );
1319 return TIC_OK;
1320 }
1321 }
1322 /* not to us and no forward */
1323 w_log( LL_SECURITY, "Tic File addressed to %s, not to us", aka2str( tic.to ) );
1324 disposeTic( &tic );
1325 return TIC_NotForUs;
1326 }
1327 }
1328
1329 /* Security Check */
1330 from_link = getLinkFromAddr( config, tic.from );
1331 if( from_link == NULL )
1332 {
1333 w_log( LL_SECURITY, "Tic from unknown link \"%s\".", aka2str( tic.from ) );
1334 disposeTic( &tic );
1335 return TIC_Security;
1336 }
1337
1338 if( tic.password && ( ( from_link->ticPwd == NULL ) ||
1339 ( stricmp( tic.password, from_link->ticPwd ) != 0 ) ) )
1340 {
1341 w_log( LL_SECURITY, "Wrong Password \"%s\" from \"%s\"", tic.password, aka2str( tic.from ) );
1342 disposeTic( &tic );
1343 return TIC_Security;
1344 }
1345
1346 /* Extract directory name from ticket pathname (strip file name), construct full name of file,
1347 * adopt full pathname into real disk file, update file name in ticket */
1348 strcpy( tickedfile, ticfile );
1349 *( strrchr( tickedfile, PATH_DELIM ) + 1 ) = 0;
1350 j = strlen( tickedfile );
1351 strcat( tickedfile, tic.file );
1352 adaptcase( tickedfile );
1353 strcpy( tic.file, tickedfile + j );
1354
1355 /* Receive file? */
1356 if( !fexist( tickedfile ) )
1357 {
1358 if( from_link->delNotReceivedTIC )
1359 {
1360 w_log( LL_TIC, "File %s from filearea %s has not been received, removing its TIC", tic.file, tic.area );
1361 disposeTic( &tic );
1362 return TIC_OK;
1363 }
1364 else
1365 {
1366 w_log( LL_TIC, "File %s from filearea %s has not been received, waiting", tic.file, tic.area );
1367 disposeTic( &tic );
1368 return TIC_NotRecvd;
1369 }
1370 }
1371
1372 #if !defined(__UNIX__)
1373 if( hidden( tickedfile ) )
1374 {
1375 w_log( LL_TIC, "File %s from filearea %s has not been completely received, waiting", tic.file, tic.area );
1376 disposeTic( &tic );
1377 return TIC_NotRecvd;
1378 }
1379 #endif
1380
1381 filearea = getFileArea( tic.area );
1382
1383 w_log( LL_DEBUGU, __FILE__ ":%u:processTic(): filearea %sfound", __LINE__,
1384 filearea ? "" : "not " );
1385 if( filearea == NULL && from_link->filefix.autoCreate )
1386 {
1387 char *descr = NULL;
1388
1389 if( tic.areadesc )
1390 descr = sstrdup( tic.areadesc );
1391 if( config->intab && descr )
1392 recodeToInternalCharset( descr );
1393 autoCreate( tic.area, descr, tic.from, NULL );
1394 filearea = getFileArea( tic.area );
1395 w_log( LL_DEBUGU, __FILE__ ":%u:processTic(): filearea %sfound", __LINE__,
1396 filearea ? "" : "not " );
1397 nfree( descr );
1398 }
1399
1400 if( filearea == NULL )
1401 {
1402 if( from_link->filefix.autoCreate )
1403 {
1404 w_log( LL_ERROR, "Cannot create File Area %s", tic.area );
1405 if( !quiet )
1406 fprintf( stderr, "Cannot create File Area %s !\n", tic.area );
1407 }
1408 else
1409 {
1410 w_log( LL_ERROR, "Cannot open File Area %s, autocreate not allowed", tic.area );
1411 if( !quiet )
1412 fprintf( stderr, "Cannot open File Area %s, autocreate not allowed !\n", tic.area );
1413 }
1414 disposeTic( &tic );
1415 return TIC_NotOpen;
1416 }
1417
1418 if( stat( tickedfile, &stbuf ) )
1419 {
1420 w_log( LL_ERR, "Can't check size of file \"%s\": %s. Skipping the file.", tickedfile,
1421 strerror( errno ) );
1422 stbuf.st_size = tic.size;
1423 return TIC_NotOpen;
1424 }
1425
1426 /* Check CRC Value and reject faulty files depending on noCRC flag */
1427 if( !filearea->noCRC && tic.crc_is_present )
1428 {
1429 unsigned long crc;
1430
1431 crc = filecrc32( tickedfile );
1432 if( ( tic.size >= 0 && ( tic.size != stbuf.st_size ) ) || ( tic.crc != crc ) )
1433 {
1434 w_log( LL_TIC, "%s of file '%s' differs with TIC. I try to find "
1435 "file with another suffix",
1436 ( tic.size != stbuf.st_size ) ? "Size" : "CRC32", tickedfile );
1437 strncpy( dirname, tickedfile, sizeof( dirname ) );
1438 pos = strrchr( dirname, PATH_DELIM );
1439 if( pos && ( pos - dirname + 4 < sizeof( dirname ) ) )
1440 {
1441 *pos = 0;
1442 findfile = pos + 1;
1443 pos = strrchr( findfile, '.' );
1444 if( pos && ( pos - dirname + 2 < sizeof( dirname ) ) )
1445 {
1446
1447 *( ++pos ) = 0;
1448 strcat( findfile, "*" );
1449 dir = husky_opendir( dirname );
1450
1451 if( dir )
1452 {
1453 while( ( file = husky_readdir( dir ) ) != NULL )
1454 {
1455 if( patimat( file, findfile ) )
1456 {
1457 if( stat( file, &stbuf ) )
1458 {
1459 w_log( LL_ERR, "Can't check size of file \"%s\": %s. Skipping the file.",
1460 file, strerror( errno ) );
1461 stbuf.st_mode = 0; /* to indicate empty structure (mode can't be zero in POSIX) */
1462 stbuf.st_size = 0;
1463 }
1464 else
1465 {
1466 if( !stbuf.st_size && !tic.size )
1467 { /* file empty AND size from TIC is 0 */
1468 /* CRC32 of an empty file is equal to zero */
1469 if( strlen( dirname ) + strlen( file ) + 1 >= sizeof( dirname ) )
1470 {
1471 w_log( LL_ERR, "Path too long (max %i bytes): \"%s%c%s\"",
1472 sizeof( dirname ), dirname, PATH_DELIM, file );
1473 }
1474 else
1475 {
1476 fileisfound = 1;
1477 sprintf( dirname + strlen( dirname ), "%c%s", PATH_DELIM, file );
1478 break;
1479 }
1480 }
1481 else if( ( tic.size < 0 ) || ( stbuf.st_size == tic.size ) )
1482 {
1483 /* size not specified in TIC OR size from TIC eq filesize */
1484 crc = filecrc32( file );
1485 if( crc == tic.crc )
1486 {
1487 if( strlen( dirname ) + strlen( file ) + 1 >= sizeof( dirname ) )
1488 {
1489 w_log( LL_ERR, "Path too long (max %i bytes): \"%s%c%s\"",
1490 sizeof( dirname ), dirname, PATH_DELIM, file );
1491 }
1492 else
1493 {
1494 fileisfound = 1;
1495 sprintf( dirname + strlen( dirname ), "%c%s", PATH_DELIM, file );
1496 break;
1497 }
1498 }
1499 }
1500 }
1501 }
1502 }
1503 husky_closedir( dir );
1504 }
1505 }
1506 }
1507
1508 if( fileisfound )
1509 {
1510 realfile = sstrdup( dirname );
1511 *( strrchr( dirname, PATH_DELIM ) ) = 0;
1512 findfile = makeUniqueDosFileName( dirname, "tmp", config );
1513 if( rename( tickedfile, findfile ) != 0 )
1514 {
1515 w_log( LL_ERROR, "Can't rename file \"%s\" to temporary \"%s\": %s", tickedfile, findfile,
1516 strerror( errno ) );
1517 nfree( findfile );
1518 nfree( realfile );
1519 disposeTic( &tic );
1520 return TIC_NotRecvd;
1521 }
1522 if( rename( realfile, tickedfile ) != 0 )
1523 {
1524 w_log( LL_ERROR, "Can't rename file \"%s\" to \"%s\": %s", realfile, tickedfile,
1525 strerror( errno ) );
1526 if( rename( findfile, tickedfile ) != 0 )
1527 {
1528 w_log( LL_ERROR, "Can't rename a file back from temporary \"%s\" to \"%s\": %s",
1529 tickedfile, findfile, strerror( errno ) );
1530 }
1531 nfree( findfile );
1532 nfree( realfile );
1533 disposeTic( &tic );
1534 return TIC_CantRename;
1535 }
1536 if( rename( findfile, realfile ) != 0 )
1537 {
1538 remove( findfile );
1539 }
1540 nfree( findfile );
1541 nfree( realfile );
1542 }
1543 else
1544 {
1545 w_log( LL_TIC, "Wrong CRC for file \"%s\", skipping this file (in tic:%08lx, need:%08lx)",
1546 tic.file, tic.crc, crc );
1547 disposeTic( &tic );
1548 return TIC_NotRecvd;
1549 }
1550 }
1551 else
1552 fileisfound = 1;
1553 }
1554 else
1555 { /* Search of a file in the size */
1556 if( stbuf.st_size == tic.size )
1557 {
1558 fileisfound = 1;
1559 }
1560 else
1561 {
1562 /* FIXME: Place here search of a file in his size (in same inbound as a ticket) */
1563 }
1564 }
1565
1566 if( !stbuf.st_mode )
1567 stat( tickedfile, &stbuf ); /* Read the size of a file if function stat() has not been called earlier */
1568 tic.size = stbuf.st_size; /* FIXME: may be wrong result for big file */
1569
1570 /* do toss zero-length files */
1571 if( !tic.size )
1572 {
1573 w_log( LL_WARNING, "File \"%s\" from filearea %s has zero size", tic.file, tic.area );
1574 }
1575
1576 writeAccess = e_writeCheck( config, filearea, getLinkFromAddr( config, tic.from ) );
1577
1578 switch ( writeAccess )
1579 {
1580 case 0:
1581 break;
1582 case 4:
1583 w_log( LL_SECURITY, "Link %s not subscribed to File Area %s", aka2str( tic.from ), tic.area );
1584 disposeTic( &tic );
1585 return TIC_WrongTIC;
1586 case 3:
1587 w_log( LL_SECURITY, "No import (or read only) from link %s", aka2str( from_link->hisAka ) );
1588 disposeTic( &tic );
1589 return TIC_WrongTIC;
1590 case 2:
1591 w_log( LL_SECURITY, "Link's %s level provides no access", aka2str( from_link->hisAka ) );
1592 disposeTic( &tic );
1593 return TIC_WrongTIC;
1594 case 1:
1595 w_log( LL_SECURITY, "The group the area %s belongs to is neither in PublicGroup nor in link's %s AccessGrp",
1596 filearea->areaName, aka2str( from_link->hisAka ) );
1597 disposeTic( &tic );
1598 return TIC_WrongTIC;
1599 }
1600
1601 rc = sendToLinks( 1, filearea, &tic, tickedfile );
1602
1603 if( rc == TIC_OK ) /* TIC_OK = 0 in htick/h/toss.h */
1604 doSaveTic( ticfile, &tic, filearea );
1605
1606 disposeTic( &tic );
1607 return ( rc );
1608 } /* processTic */
1609
1610 /* Toss TIC-files in the specified directory
1611 */
processDir(char * directory,e_tossSecurity sec)1612 void processDir( char *directory, e_tossSecurity sec )
1613 {
1614 husky_DIR *dir;
1615 char *file;
1616 char *dummy = NULL;
1617 int rc;
1618
1619 if( ( directory == NULL ) )
1620 {
1621 w_log( LL_ERROR,
1622 __FILE__
1623 ":%i: Parameter is a NULL pointer: processDir(%s%s%s,sec). This is a bug, please report it to developers.",
1624 __LINE__, directory ? "\"" : "", directory ? directory : "NULL", directory ? "\"" : "" );
1625 return;
1626 }
1627
1628 dir = husky_opendir( directory );
1629 if( dir == NULL )
1630 return;
1631
1632 while( ( file = husky_readdir( dir ) ) != NULL )
1633 {
1634 #ifdef DEBUG_HPT
1635 printf( "testing %s\n", file );
1636 #endif
1637
1638 if( ( ( cmToss == 1 ) && ( patimat( file, "*.TIC" ) == 1 ) ) ||
1639 ( ( cmToss == 2 ) && ( ( patimat( file, "*.BAD" ) == 1 ) ||
1640 ( patimat( file, "*.SEC" ) == 1 ) ||
1641 ( patimat( file, "*.ACS" ) == 1 ) ||
1642 ( patimat( file, "*.NTU" ) == 1 ) ) ) )
1643 {
1644 xstrscat( &dummy, directory, file, NULL );
1645
1646 #if !defined(__UNIX__)
1647 if( !hidden( dummy ) )
1648 {
1649 #endif
1650 rc = processTic( dummy, sec );
1651 if( cmToss == 1 )
1652 {
1653 switch ( rc )
1654 {
1655 case TIC_Security: /* pktpwd problem */
1656 changeFileSuffix( dummy, "sec", 1 );
1657 break;
1658 case TIC_NotOpen: /* could not open file */
1659 case TIC_CantRename:
1660 case TIC_IOError:
1661 changeFileSuffix( dummy, "acs", 1 );
1662 break;
1663 case TIC_WrongTIC: /* not/wrong pkt */
1664 changeFileSuffix( dummy, "bad", 1 );
1665 break;
1666 case TIC_NotForUs: /* not to us */
1667 changeFileSuffix( dummy, "ntu", 1 );
1668 break;
1669 case TIC_NotRecvd: /* file not recieved */
1670 break;
1671 case TIC_OK: /* OK */
1672 remove( dummy );
1673 break;
1674 default: /* Unknown, do nothing */
1675 break;
1676 } /* switch */
1677 }
1678 else if( rc == TIC_OK )
1679 {
1680 remove( dummy );
1681 }
1682 #if !defined(__UNIX__)
1683 }
1684 #endif
1685 nfree( dummy );
1686 } /* if */
1687 } /* while */
1688 husky_closedir( dir );
1689 } /* processDir() */
1690
1691 /* Scan directory with postponed files
1692 */
checkTmpDir(void)1693 void checkTmpDir( void )
1694 {
1695 char tmpdir[256], newtickedfile[256], newticfile[256];
1696 husky_DIR *dir = NULL;
1697 char *file = NULL;
1698 s_link *link = NULL;
1699 s_ticfile tic;
1700 s_area *filearea = NULL;
1701 FILE *flohandle = NULL;
1702 int error = 0;
1703
1704 w_log( LL_TIC, "Checking tmp dir" );
1705 strcpy( tmpdir, config->busyFileDir );
1706 dir = husky_opendir( tmpdir );
1707 if( dir == NULL )
1708 return;
1709
1710 while( ( file = husky_readdir( dir ) ) != NULL )
1711 {
1712 int file_length = strlen( file );
1713
1714 if( file_length != 12 )
1715 continue; /* Check only ticket files: 8 characters followed by ".tic" */
1716 if( stricmp( file + 8, ".TIC" ) == 0 )
1717 {
1718 char *ticfile = ( char * )smalloc( strlen( tmpdir ) + file_length + 1 );
1719
1720 if( !ticfile )
1721 continue;
1722 strcpy( ticfile, tmpdir );
1723 strcat( ticfile, file );
1724
1725 memset( &tic, 0, sizeof( tic ) );
1726 if( parseTic( ticfile, &tic ) != parseTic_success )
1727 continue;
1728 if( checkTic( ticfile, &tic ) )
1729 continue;
1730 link = getLinkFromAddr( config, tic.to );
1731 if( !link )
1732 continue;
1733 /* createFlo doesn't support ASO!!! */
1734 /* if (createFlo(link,cvtFlavour2Prio(link->fileEchoFlavour))==0) { */
1735 if( createOutboundFileNameAka( link, link->fileEchoFlavour, FLOFILE, SelectPackAka( link ) )
1736 == 0 )
1737 {
1738 filearea = getFileArea( tic.area );
1739 if( filearea != NULL )
1740 {
1741 if( filearea->msgbType != MSGTYPE_PASSTHROUGH && !filearea->sendorig )
1742 strcpy( newtickedfile, filearea->fileName );
1743 else
1744 strcpy( newtickedfile, config->passFileAreaDir );
1745 strcat( newtickedfile, tic.file );
1746 adaptcase( newtickedfile );
1747 if( !link->noTIC )
1748 {
1749 if( config->separateBundles )
1750 {
1751 strcpy( newticfile, link->floFile );
1752 sprintf( strrchr( newticfile, '.' ), ".sep%c", PATH_DELIM );
1753 }
1754 else
1755 {
1756 strcpy( newticfile, config->ticOutbound );
1757 }
1758 _createDirectoryTree( newticfile );
1759 strcat( newticfile, strrchr( ticfile, PATH_DELIM ) + 1 );
1760 if( !fexist( ticfile ) )
1761 w_log( LL_ERROR, "File %s not found", ticfile );
1762 else if( move_file( ticfile, newticfile, 1 ) != 0 )
1763 { /* overwrite existing file if not the same */
1764 w_log( LL_ERROR, "File %s not moveable to %s: %s",
1765 ticfile, newticfile, strerror( errno ) );
1766 error = 1;
1767 }
1768 }
1769 else
1770 remove( ticfile );
1771 if( !error )
1772 {
1773 flohandle = fopen( link->floFile, "a" );
1774 fprintf( flohandle, "%s\n", newtickedfile );
1775 if( !link->noTIC )
1776 fprintf( flohandle, "^%s\n", newticfile );
1777 fclose( flohandle );
1778
1779 w_log( LL_TIC, "Forwarding save file \"%s\" for %s",
1780 tic.file, aka2str( link->hisAka ) );
1781 }
1782 } /* if filearea */
1783 } /* if createFlo */
1784 if( link->bsyFile )
1785 {
1786 remove( link->bsyFile );
1787 nfree( link->bsyFile );
1788 }
1789 nfree( link->floFile );
1790 disposeTic( &tic );
1791 nfree( ticfile );
1792 } /* if ".TIC" */
1793 } /* while */
1794 husky_closedir( dir );
1795 }
1796
1797 /*
1798 * Return: 0 if error, 1 if success
1799 */
putMsgInArea(s_area * echo,s_message * msg,int strip,dword forceattr)1800 int putMsgInArea( s_area * echo, s_message * msg, int strip, dword forceattr )
1801 {
1802 char *ctrlBuff, *textStart, *textWithoutArea;
1803 UINT textLength = ( UINT ) msg->textLength;
1804 HAREA harea = NULL;
1805 HMSG hmsg;
1806 XMSG xmsg;
1807 char /**slash,*/ *p, *q, *tiny;
1808 int rc = 0;
1809
1810 if( ( echo == NULL ) || ( msg == NULL ) )
1811 {
1812 w_log( LL_ERROR, __FILE__ ":%i: Parameter is a NULL pointer: putMsgInArea(%s,%s,%i,%u). "
1813 "This is a bug, please report it to developers.",
1814 __LINE__, echo ? "echo" : "NULL", msg ? "msg" : "NULL", strip, ( unsigned )forceattr );
1815 return 0;
1816 }
1817
1818 if( echo->msgbType == MSGTYPE_PASSTHROUGH )
1819 {
1820 w_log( LL_ERROR, "Can't put a message to passthrough area %s!", echo->areaName );
1821 return rc;
1822 }
1823
1824 if( !msg->netMail )
1825 {
1826 msg->destAddr.zone = echo->useAka->zone;
1827 msg->destAddr.net = echo->useAka->net;
1828 msg->destAddr.node = echo->useAka->node;
1829 msg->destAddr.point = echo->useAka->point;
1830 }
1831
1832 harea = MsgOpenArea( ( UCHAR * ) echo->fileName, MSGAREA_CRIFNEC,
1833 ( word ) ( echo->msgbType | ( msg->netMail ? 0 : MSGTYPE_ECHO ) ) );
1834 if( harea != NULL )
1835 {
1836 hmsg = MsgOpenMsg( harea, MOPEN_CREATE, 0 );
1837 if( hmsg != NULL )
1838 {
1839
1840 textWithoutArea = msg->text;
1841
1842 if( ( strip == 1 ) && ( strncmp( msg->text, "AREA:", 5 ) == 0 ) )
1843 {
1844 /* jump over AREA:xxxxx\r */
1845 while( *( textWithoutArea ) != '\r' )
1846 textWithoutArea++;
1847 textWithoutArea++;
1848 textLength -= ( size_t ) ( textWithoutArea - msg->text );
1849 }
1850
1851 if( echo->killSB )
1852 {
1853 tiny = strrstr( textWithoutArea, " * Origin:" );
1854 if( tiny == NULL )
1855 tiny = textWithoutArea;
1856 if( NULL != ( p = strstr( tiny, "\rSEEN-BY: " ) ) )
1857 {
1858 p[1] = '\0';
1859 textLength = ( size_t ) ( p - textWithoutArea + 1 );
1860 }
1861 }
1862 else if( echo->tinySB )
1863 {
1864 tiny = strrstr( textWithoutArea, " * Origin:" );
1865 if( tiny == NULL )
1866 tiny = textWithoutArea;
1867 if( NULL != ( p = strstr( tiny, "\rSEEN-BY: " ) ) )
1868 {
1869 p++;
1870 if( NULL != ( q = strstr( p, "\001PATH: " ) ) )
1871 {
1872 /* memmove(p,q,strlen(q)+1); */
1873 memmove( p, q, textLength - ( size_t ) ( q - textWithoutArea ) + 1 );
1874 textLength -= ( size_t ) ( q - p );
1875 }
1876 else
1877 {
1878 p[0] = '\0';
1879 textLength = ( size_t ) ( p - textWithoutArea );
1880 }
1881 }
1882 }
1883
1884 {
1885 byte *bb; /* Prevent GCC warning "dereferencing type-punned pointer will break strict-aliasing rules" */
1886
1887 ctrlBuff = ( char * )CopyToControlBuf( textWithoutArea, &bb, &textLength );
1888 textStart = bb;
1889 }
1890 /* textStart is a pointer to the first non-kludge line */
1891 xmsg = createXMSG( config, msg, NULL, forceattr, NULL );
1892
1893 if( MsgWriteMsg( hmsg, 0, &xmsg, ( byte * ) textStart, ( dword )
1894 textLength, ( dword ) textLength,
1895 ( dword ) strlen( ctrlBuff ), ( byte * ) ctrlBuff ) != 0 )
1896 w_log( LL_ERROR, "Could not write msg in %s!", echo->fileName );
1897 else
1898 rc = 1; /* normal exit */
1899
1900 if( MsgCloseMsg( hmsg ) != 0 )
1901 {
1902 w_log( LL_ERROR, "Could not close msg in %s!", echo->fileName );
1903 rc = 0;
1904 }
1905 nfree( ctrlBuff );
1906
1907 }
1908 else
1909 w_log( LL_ERROR, "Could not create new msg in %s!", echo->fileName );
1910 /* endif */
1911 MsgCloseArea( harea );
1912 }
1913 else
1914 w_log( LL_ERROR, "Could not open/create EchoArea %s!", echo->fileName );
1915 /* endif */
1916 return rc;
1917 }
1918
1919 /*
1920 * Return: o if error, 1 of success
1921 */
putMsgInBadArea(s_message * msg,hs_addr pktOrigAddr)1922 int putMsgInBadArea( s_message * msg, hs_addr pktOrigAddr )
1923 {
1924 char *tmp = NULL, *line = NULL, *textBuff = NULL, *areaName = NULL, *reason = NULL;
1925
1926 if( ( msg == NULL ) )
1927 {
1928 w_log( LL_ERROR,
1929 __FILE__
1930 ":%i: Parameter is a NULL pointer: putMsgInBadArea(NULL,pktOrigAddr). This is a bug, please report it to developers.",
1931 __LINE__ );
1932 return 0;
1933 }
1934
1935 /* get real name area */
1936 line = strchr( msg->text, '\r' );
1937 if( strncmp( msg->text, "AREA:", 5 ) == 0 )
1938 {
1939 *line = 0;
1940 xstrcat( &areaName, msg->text + 5 );
1941 *line = '\r';
1942 }
1943 reason = "report to passthrough area";
1944 tmp = msg->text;
1945
1946 while( ( line = strchr( tmp, '\r' ) ) != NULL )
1947 {
1948 if( *( line + 1 ) == '\x01' )
1949 tmp = line + 1;
1950 else
1951 {
1952 tmp = line + 1;
1953 *line = 0;
1954 break;
1955 }
1956 }
1957
1958 xstrscat( &textBuff, msg->text, "\rFROM: ", aka2str( pktOrigAddr ), "\rREASON: ", reason, "\r",
1959 NULL );
1960
1961 if( areaName )
1962 xscatprintf( &textBuff, "AREANAME: %s\r\r", areaName );
1963 xstrcat( &textBuff, tmp );
1964 nfree( areaName );
1965 nfree( msg->text );
1966 msg->text = textBuff;
1967 msg->textLength = strlen( msg->text );
1968 if( putMsgInArea( &( config->badArea ), msg, 0, 0 ) )
1969 {
1970 return 1;
1971 }
1972 return 0;
1973 }
1974
1975 /* Append tearline and origin lines into message text and create message in the
1976 * specified area.
1977 * If areaName is NULL pointer or does not exist: netmail will be placed in the first
1978 * netmail area, echomail will be placed in badarea.
1979 */
writeMsgToSysop(s_message * msg,char * areaName,char * origin)1980 void writeMsgToSysop( s_message * msg, char *areaName, char *origin )
1981 {
1982 s_area *echo;
1983
1984 if( ( msg == NULL ) )
1985 {
1986 w_log( LL_ERROR,
1987 __FILE__
1988 ":%i: Parameter is a NULL pointer: writeMsgToSysop(NULL,...). This is a bug, please report it to developers.",
1989 __LINE__ );
1990 return;
1991 }
1992
1993 xscatprintf( &( msg->text ), " \r--- %s\r * Origin: %s (%s)\r",
1994 ( config->tearline ) ? config->tearline : "",
1995 origin ? origin : ( config->origin ) ? config->origin : config->name,
1996 aka2str( msg->origAddr ) );
1997
1998 msg->textLength = strlen( msg->text );
1999 if( msg->netMail == 1 )
2000 writeNetmail( msg, areaName );
2001 else
2002 {
2003 echo = getArea( config, areaName );
2004 if( echo != &( config->badArea ) && echo->msgbType != MSGTYPE_PASSTHROUGH )
2005 {
2006 putMsgInArea( echo, msg, 1, MSGLOCAL );
2007 w_log( LL_POSTING, "Post report message to %s area", echo->areaName );
2008 }
2009 else
2010 {
2011 w_log( LL_POSTING, "Post report message to %s area", config->badArea.areaName );
2012 putMsgInBadArea( msg, msg->origAddr );
2013 }
2014 }
2015 }
2016
toss()2017 void toss( )
2018 {
2019
2020 w_log( LL_INFO, "Start tossing..." );
2021
2022 if (config->localInbound && config->localInbound[0] ) processDir( config->localInbound, secLocalInbound );
2023 if (config->protInbound && config->protInbound[0] ) processDir( config->protInbound, secProtInbound );
2024 if (config->inbound && config->inbound[0] ) processDir( config->inbound, secInbound );
2025
2026 }
2027