1 /*
2 * RNtrack - FTN message tracker/router
3 *
4 * attach.cpp - Work with attaches
5 *
6 * Copyright (c) 2003-2005 Alex Soukhotine, 2:5030/1157
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * $Id: attach.cpp 257 2020-01-30 18:19:33Z dukelsky $
14 */
15
16 #include "compiler.h"
17 #ifdef HAVE_CONFIG_H
18 #include "aconfig.h"
19 #endif
20
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #ifdef HAVE_UNISTD_H
24 #include <unistd.h>
25 #endif
26 #ifdef HAVE_DOS_H
27 #include <dos.h>
28 #endif
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include "string.hpp"
32 #include <ctype.h>
33 #ifdef HAVE_FCNTL_H
34 #include <fcntl.h>
35 #endif
36 #include <errno.h>
37 #include "constant.hpp"
38 #include "help.hpp"
39 #include "utils.hpp"
40 #include "vars.hpp"
41 #include "configure.hpp"
42 #include "fidoaddr.hpp"
43 #include "scandir.hpp"
44 #include "attach.hpp"
45 #include "outbound.hpp"
46 #include "mytypes.hpp"
47 #include "msg.hpp"
48 #if defined(HAS_IO_H) || defined(HAVE_IO_H)
49 #include <io.h>
50 #endif
51
52 #ifdef __WATCOMC__
53 #undef far
54 #endif
55
56 #ifdef __NT__
57 #undef byte
58 #undef EXPENTRY
59 #include <windows.h>
60 #endif
61
62 // --------------------------------------------------------------------
63 static char NewPath[BUFF_SIZE];
64 static char NewSubj[73];
65 static int AttSize;
66 static char FboxPath[BUFF_SIZE];
67 // --------------------------------------------------------------------
68
BaseName(char * name)69 static char * BaseName(char * name)
70 {
71 static char Buff[BUFF_SIZE];
72 char Buff1[BUFF_SIZE];
73 char * tmt;
74
75 Buff[0] = '\0';
76 RSTRLCPY(Buff1, name, BUFF_SIZE);
77
78 if((tmt = strrchr(Buff1, PATHDELIMC)) != NULL)
79 {
80 tmt++;
81 RSTRLCPY(Buff1, tmt, BUFF_SIZE);
82 }
83
84 if((tmt = strrchr(Buff1, ':')) != NULL)
85 {
86 tmt++;
87 RSTRLCPY(Buff1, tmt, BUFF_SIZE);
88 }
89
90 if((tmt = strrchr(Buff1, '/')) != NULL)
91 {
92 tmt++;
93 RSTRLCPY(Buff1, tmt, BUFF_SIZE);
94 }
95
96 if((tmt = strrchr(Buff1, '\\')) != NULL)
97 {
98 tmt++;
99 RSTRLCPY(Buff1, tmt, BUFF_SIZE);
100 }
101
102 RSTRLCAT(Buff, Buff1, BUFF_SIZE);
103 return Buff;
104 } // BaseName
105
FullName(char * name)106 static char * FullName(char * name)
107 {
108 static char Buff[BUFF_SIZE];
109
110 if(FileInbound != NULL)
111 {
112 RSTRLCPY(Buff, FileInbound, BUFF_SIZE);
113 }
114 else
115 {
116 Buff[0] = '\0';
117 }
118
119 if((strchr(name, PATHDELIMC) == NULL
120 #ifndef __unix__
121 && strchr(name, ':') == NULL
122 #endif
123 ) || (IgnoreAttachPath != FALSE))
124 {
125 RSTRLCAT(Buff, BaseName(name), BUFF_SIZE);
126 }
127 else
128 {
129 RSTRLCPY(Buff, name, BUFF_SIZE);
130 }
131
132 return Buff;
133 } // FullName
134
_PrintAttach(char * Buff)135 int _PrintAttach(char * Buff)
136 {
137 Log.Level(LOGI) << "Attached '" << FullName(Buff) << "'" << EOL;
138 return TRUE;
139 }
140
_AttToSize(char * Buff)141 int _AttToSize(char * Buff)
142 {
143 int i;
144 int fh;
145 char * tmt;
146
147 tmt = FullName(Buff);
148 #ifdef __NT__
149 OemToChar(tmt, tmt);
150 #endif
151 fh = open(tmt, O_RDONLY | O_BINARY);
152 #ifdef __NT__
153 CharToOem(tmt, tmt);
154 #endif
155 i = errno;
156
157 if(fh == -1)
158 {
159 if(i != ENOENT)
160 {
161 Log.Level(LOGE) << " Unable to open file: '" << tmt <<
162 "', Errno: " << i << EOL;
163 return FALSE;
164 }
165 else
166 {
167 return TRUE;
168 }
169 }
170
171 i = filelength(fh);
172
173 if(i == -1)
174 {
175 i = errno;
176 close(fh);
177 Log.Level(LOGE) << " Unable to get size of file: '" << tmt <<
178 "', Errno: " << i << EOL;
179 return FALSE;
180 }
181
182 close(fh);
183 AttSize += i;
184 return TRUE;
185 } // _AttToSize
186
_AddToLo(char * Buff)187 int _AddToLo(char * Buff)
188 {
189 char tmt[BUFF_SIZE];
190
191 tmt[0] = NewPath[0];
192 tmt[1] = '\0';
193
194 RSTRLCAT(tmt, FullName(Buff), BUFF_SIZE);
195
196 AddToLo(tmt);
197 return TRUE;
198 }
199
_AddToFboxLo(char * Buff)200 int _AddToFboxLo(char * Buff)
201 {
202 char tmt[BUFF_SIZE];
203
204 tmt[0] = NewPath[0];
205 tmt[1] = '\0';
206
207 if(FboxPath[0] != '\0')
208 {
209 RSTRLCAT(tmt, FboxPath, BUFF_SIZE);
210
211 if(tmt[strlen(tmt) - 1] != PATHDELIMC)
212 {
213 RSTRLCAT(tmt, PATHDELIMS, BUFF_SIZE);
214 }
215
216 RSTRLCAT(tmt, BaseName(Buff), BUFF_SIZE);
217 }
218 else
219 {
220 RSTRLCAT(tmt, FullName(Buff), BUFF_SIZE);
221 }
222
223 AddToLo(tmt);
224 return TRUE;
225 }
226
_DelFromLo(char * Buff)227 int _DelFromLo(char * Buff)
228 {
229 DelFromLo(FullName(Buff));
230 return TRUE;
231 }
232
_ChangePath(char * Buff)233 int _ChangePath(char * Buff)
234 {
235 RSTRLCAT(NewSubj, NewPath, 72);
236 RSTRLCAT(NewSubj, BaseName(Buff), 72);
237 RSTRLCAT(NewSubj, " ", 72);
238 return TRUE;
239 }
240
_ToLowerPath(char * Buff)241 int _ToLowerPath(char * Buff)
242 {
243 char Buff1[BUFF_SIZE];
244
245 RSTRLCPY(Buff1, Buff, BUFF_SIZE);
246
247 for(unsigned int i = 0; i < strlen(Buff1); i++)
248 {
249 Buff1[i] = tolower(Buff1[i]);
250 }
251 RSTRLCAT(NewSubj, Buff1, 72);
252 RSTRLCAT(NewSubj, " ", 72);
253 return TRUE;
254 }
255
_ToUpperPath(char * Buff)256 int _ToUpperPath(char * Buff)
257 {
258 char Buff1[BUFF_SIZE];
259
260 RSTRLCPY(Buff1, Buff, BUFF_SIZE);
261
262 for(unsigned int i = 0; i < strlen(Buff1); i++)
263 {
264 Buff1[i] = toupper(Buff1[i]);
265 }
266 RSTRLCAT(NewSubj, Buff1, 72);
267 RSTRLCAT(NewSubj, " ", 72);
268 return TRUE;
269 }
270
_DeleteAttach(char * Buff)271 int _DeleteAttach(char * Buff)
272 {
273 char * tmt;
274
275 tmt = FullName(Buff);
276 #ifdef __NT__
277 OemToChar(tmt, tmt);
278 #endif
279
280 if(access(tmt, F_OK) != 0)
281 {
282 #ifdef __NT__
283 CharToOem(tmt, tmt);
284 #endif
285 Log.Level(LOGI) << " File not found: '" << tmt << "'" << EOL;
286 return TRUE;
287 }
288
289 if(unlink(tmt) != 0)
290 {
291 #ifdef __NT__
292 CharToOem(tmt, tmt);
293 #endif
294 Log.Level(LOGE) << " Unable to delete: '" << tmt << "'" << EOL;
295 return FALSE;
296 }
297
298 #ifdef __NT__
299 CharToOem(tmt, tmt);
300 #endif
301 Log.Level(LOGI) << " Delete: '" << tmt << "'" << EOL;
302 return TRUE;
303 } // _DeleteAttach
304
_AttachExists(char * Buff)305 int _AttachExists(char * Buff)
306 {
307 struct stat dd;
308 char * tmt;
309
310 tmt = FullName(Buff);
311 #ifdef __NT__
312 OemToChar(tmt, tmt);
313 #endif
314
315 if(stat(tmt, &dd) != 0)
316 {
317 return FALSE;
318 }
319
320 if(!S_ISREG(dd.st_mode))
321 {
322 return FALSE;
323 }
324
325 #if defined (__MINGW32__) || defined (_MSC_VER)
326
327 if(SkipHiddenFiles)
328 {
329 struct _finddata_t fd;
330 int h = (int)_findfirst(tmt, &fd);
331
332 if(h != -1)
333 {
334 _findclose(h);
335
336 if(!strcmp(fd.name, tmt) && (fd.attrib | _A_HIDDEN))
337 {
338 return FALSE;
339 }
340 }
341 }
342
343 #elif defined (__DJGPP__)
344
345 if(SkipHiddenFiles)
346 {
347 unsigned int attrs;
348 _dos_getfileattr(tmt, &attrs);
349
350 if(attrs | _A_HIDDEN)
351 {
352 return FALSE;
353 }
354 }
355
356 #elif !defined (__unix__)
357
358 if(SkipHiddenFiles && (dd.st_attr & 2))
359 {
360 return FALSE;
361 }
362
363 #endif // if defined (__MINGW32__) || defined (_MSC_VER)
364 return TRUE;
365 } // _AttachExists
366
_MoveAttach(char * Buff)367 int _MoveAttach(char * Buff)
368 {
369 char * tmt;
370 char B[BUFF_SIZE];
371
372 tmt = FullName(Buff);
373 #ifdef __NT__
374 OemToChar(tmt, tmt);
375 #endif
376
377 if(access(tmt, F_OK) != 0)
378 {
379 #ifdef __NT__
380 CharToOem(tmt, tmt);
381 #endif
382 Log.Level(LOGI) << " File not found: '" << tmt << "'" << EOL;
383 return TRUE;
384 }
385
386 RSTRLCPY(B, NewPath, BUFF_SIZE);
387 RSTRLCAT(B, BaseName(Buff), BUFF_SIZE);
388 tmt = FullName(Buff);
389 #ifdef __NT__
390 OemToChar(tmt, tmt);
391 OemToChar(B, B);
392 #endif
393
394 if(!FileMove(B, tmt))
395 {
396 #ifdef __NT__
397 CharToOem(tmt, tmt);
398 #endif
399 Log.Level(LOGE) << " Unable to move file '" << tmt << "' to " <<
400 NewPath << EOL;
401 return FALSE;
402 }
403
404 #ifdef __NT__
405 CharToOem(tmt, tmt);
406 #endif
407 Log.Level(LOGI) << " Move: '" << tmt << "' ==> " << NewPath << EOL;
408 return TRUE;
409 } // _MoveAttach
410
_CopyAttach(char * Buff)411 int _CopyAttach(char * Buff)
412 {
413 char * tmt;
414 char B[BUFF_SIZE];
415
416 tmt = FullName(Buff);
417 #ifdef __NT__
418 OemToChar(tmt, tmt);
419 #endif
420
421 if(access(tmt, F_OK) != 0)
422 {
423 #ifdef __NT__
424 CharToOem(tmt, tmt);
425 #endif
426 Log.Level(LOGI) << " File not found: '" << tmt <<
427 "', can't copy." << EOL;
428 return TRUE;
429 }
430
431 RSTRLCPY(B, NewPath, BUFF_SIZE);
432 RSTRLCAT(B, BaseName(Buff), BUFF_SIZE);
433 tmt = FullName(Buff);
434 #ifdef __NT__
435 OemToChar(tmt, tmt);
436 OemToChar(B, B);
437 #endif
438
439 if(!FileCopy(B, tmt))
440 {
441 #ifdef __NT__
442 CharToOem(tmt, tmt);
443 #endif
444 Log.Level(LOGE) << " Unable to copy file '" << tmt << "' to " <<
445 NewPath << EOL;
446 return FALSE;
447 }
448
449 #ifdef __NT__
450 CharToOem(tmt, tmt);
451 #endif
452 Log.Level(LOGI) << " Copy: '" << tmt << "' ==> " << NewPath << EOL;
453 return TRUE;
454 } // _CopyAttach
455
456 // --------------------------------------------------------------------
457 #if defined (__unix__) || defined (__EMX__)
458
459 typedef int (*faff)(char * b);
460
ForAllFiles(faff Action,cMSG & m)461 int ForAllFiles(faff Action, cMSG & m)
462 {
463 #else
464 int ForAllFiles(int (* Action)(char * Fname), cMSG & m)
465 {
466 #endif
467 // For all Files attached to message do Action.
468 // return Action value.
469 // Action - int Action(char *FName);
470 char Buff[73];
471 char * tmt;
472
473 if(strlen(m._Subject) == 0)
474 {
475 return FALSE;
476 }
477
478 memset(Buff, 0, 73);
479 RSTRLCPY(Buff, m._Subject, 72);
480 tmt = Buff;
481
482 while(*tmt == ' ')
483 {
484 tmt++;
485 }
486
487 if(*tmt == '\0')
488 {
489 return FALSE;
490 }
491
492 while(*tmt != '\0')
493 {
494 while(*tmt == ' ')
495 {
496 tmt++;
497 }
498
499 if(*tmt == '\0')
500 {
501 break;
502 }
503
504 int i;
505 i = FALSE;
506
507 if(strchr(tmt, ' ') != NULL)
508 {
509 i = TRUE;
510 *strchr(tmt, ' ') = '\0';
511 }
512
513 if(!Action(tmt))
514 {
515 return FALSE;
516 }
517
518 while(*tmt != '\0')
519 {
520 tmt++;
521 }
522
523 if(i)
524 {
525 tmt++;
526 }
527 }
528 return TRUE;
529 } // ForAllFiles
530
531 // --------------------------------------------------------------------
532
533 int PrintAttach(cMSG & m)
534 {
535 return ForAllFiles(&_PrintAttach, m);
536 }
537
538 int AddAttachToLo(cMSG & m)
539 {
540 NewPath[0] = '\0';
541
542 if(m.fTFS)
543 {
544 NewPath[0] = '#';
545 }
546
547 if(m.fKFS)
548 {
549 NewPath[0] = '^';
550 }
551
552 return ForAllFiles(&_AddToLo, m);
553 }
554
555 int AddFboxAttachToLo(cMSG & m, char * path)
556 {
557 NewPath[0] = '\0';
558
559 if(m.fTFS)
560 {
561 NewPath[0] = '#';
562 }
563
564 if(m.fKFS)
565 {
566 NewPath[0] = '^';
567 }
568
569 RSTRLCPY(FboxPath, path, BUFF_SIZE);
570 return ForAllFiles(&_AddToFboxLo, m);
571 }
572
573 int DelAttachFromLo(cMSG & m)
574 {
575 return ForAllFiles(&_DelFromLo, m);
576 }
577
578 int DeleteAttach(cMSG & m)
579 {
580 return ForAllFiles(&_DeleteAttach, m);
581 }
582
583 int ChangePath(cMSG & m, char * Path)
584 {
585 int rc;
586
587 RSTRLCPY(NewPath, Path, BUFF_SIZE);
588 memset(NewSubj, 0, 73);
589
590 if(strlen(NewPath) != 0 && NewPath[strlen(NewPath) - 1] != PATHDELIMC)
591 {
592 RSTRLCAT(NewPath, PATHDELIMS, BUFF_SIZE);
593 }
594
595 rc = ForAllFiles(&_ChangePath, m);
596
597 if(!rc)
598 {
599 return FALSE;
600 }
601
602 if(NewSubj[0] != '\0')
603 {
604 NewSubj[strlen(NewSubj) - 1] = '\0';
605 }
606
607 if(strlen(NewSubj) > 71)
608 {
609 Log.Level(LOGE) << "New subject too long. '" << NewSubj << "'" << EOL;
610 return FALSE;
611 }
612
613 RSTRLCPY(m._Subject, NewSubj, 72);
614 return TRUE;
615 } // ChangePath
616
617 int ToLowerPath(cMSG & m)
618 {
619 int rc;
620
621 memset(NewSubj, 0, 73);
622 rc = ForAllFiles(&_ToLowerPath, m);
623
624 if(!rc)
625 {
626 return FALSE;
627 }
628
629 if(NewSubj[0] != '\0')
630 {
631 NewSubj[strlen(NewSubj) - 1] = '\0';
632 }
633
634 if(strlen(NewSubj) > 71)
635 {
636 Log.Level(LOGE) << "New subject too long. '" << NewSubj << "'" << EOL;
637 return FALSE;
638 }
639
640 RSTRLCPY(m._Subject, NewSubj, 72);
641 return TRUE;
642 }
643
644 int ToUpperPath(cMSG & m)
645 {
646 int rc;
647
648 memset(NewSubj, 0, 73);
649 rc = ForAllFiles(&_ToUpperPath, m);
650
651 if(!rc)
652 {
653 return FALSE;
654 }
655
656 if(NewSubj[0] != '\0')
657 {
658 NewSubj[strlen(NewSubj) - 1] = '\0';
659 }
660
661 if(strlen(NewSubj) > 71)
662 {
663 Log.Level(LOGE) << "New subject too long. '" << NewSubj << "'" << EOL;
664 return FALSE;
665 }
666
667 RSTRLCPY(m._Subject, NewSubj, 72);
668 return TRUE;
669 }
670
671 int GetAttSize(cMSG & m)
672 {
673 int rc;
674
675 AttSize = 0;
676 rc = ForAllFiles(&_AttToSize, m);
677
678 if(!rc)
679 {
680 return -1;
681 }
682
683 return AttSize;
684 }
685
686 int MoveAttach(cMSG & m, char * Path)
687 {
688 int rc;
689
690 RSTRLCPY(NewPath, Path, BUFF_SIZE);
691 memset(NewSubj, 0, 73);
692
693 if(strlen(NewPath) != 0 && NewPath[strlen(NewPath) - 1] != PATHDELIMC)
694 {
695 RSTRLCAT(NewPath, PATHDELIMS, BUFF_SIZE);
696 }
697
698 rc = ForAllFiles(&_ChangePath, m);
699
700 if(!rc)
701 {
702 return FALSE;
703 }
704
705 if(NewSubj[0] != '\0')
706 {
707 NewSubj[strlen(NewSubj) - 1] = '\0';
708 }
709
710 if(strlen(NewSubj) > 71)
711 {
712 Log.Level(LOGE) << "New subject too long. '" << NewSubj << "'" << EOL;
713 return FALSE;
714 }
715
716 rc = ForAllFiles(&_MoveAttach, m);
717
718 if(!rc)
719 {
720 return FALSE;
721 }
722
723 // strncpy(m._Subject,NewSubj,72);
724 return TRUE;
725 } // MoveAttach
726
727 int CopyAttach(cMSG & m, char * Path)
728 {
729 int rc;
730
731 RSTRLCPY(NewPath, Path, BUFF_SIZE);
732
733 if(strlen(NewPath) != 0 && NewPath[strlen(NewPath) - 1] != PATHDELIMC)
734 {
735 RSTRLCAT(NewPath, PATHDELIMS, BUFF_SIZE);
736 }
737
738 rc = ForAllFiles(&_CopyAttach, m);
739
740 if(!rc)
741 {
742 return FALSE;
743 }
744
745 return TRUE;
746 }
747
748 int AttachExists(cMSG & m)
749 {
750 return ForAllFiles(&_AttachExists, m);
751 }
752
753 // --------------------------------------------------------------------
754 int SetFileInbound(char * tmt)
755 {
756 IndBiList<ScanDir>::ElemPtr sd;
757 size_t size;
758
759 sd = ScanDirs.GetLast();
760
761 if(sd == NULL)
762 {
763 if(FileInbound != NULL)
764 {
765 yyerror("File inbound directory already defined.");
766 return -1;
767 }
768 }
769 else
770 {
771 if(sd->_FileInbound != NULL)
772 {
773 yyerror("File inbound directory for this scandir already defined.");
774 return -1;
775 }
776 }
777
778 if(strlen(tmt) == 0)
779 {
780 yyerror("Missing parameter: Inbound directory name.");
781 return -1;
782 }
783
784 if(!DirExists(tmt))
785 {
786 yyerror("Unable to open file inbound directory.");
787 return -1;
788 }
789
790 size = strlen(tmt) + 2;
791
792 if(sd == NULL)
793 {
794 FileInbound = (char *)malloc(size);
795 CheckMem(FileInbound);
796 RSTRLCPY(FileInbound, tmt, size);
797
798 if(FileInbound[strlen(FileInbound) - 1] != PATHDELIMC)
799 {
800 RSTRLCAT(FileInbound, PATHDELIMS, size);
801 }
802 }
803 else
804 {
805 sd->_FileInbound = (char *)malloc(size);
806 CheckMem(sd->_FileInbound);
807 RSTRLCPY(sd->_FileInbound, tmt, size);
808
809 if(FileInbound[strlen(sd->_FileInbound) - 1] != PATHDELIMC)
810 {
811 RSTRLCAT(sd->_FileInbound, PATHDELIMS, size);
812 }
813 }
814
815 return 0;
816 } // SetFileInbound
817
818 int SetSkipHiddenFiles(void)
819 {
820 if(SkipHiddenFiles)
821 {
822 yyerror("SkipHiddenFiles already set.");
823 return -1;
824 }
825
826 SkipHiddenFiles = TRUE;
827 return 0;
828 }
829
830 // ---------------------------- END --------------------------------------
831