1 /*****************************************************************************
2 * HTICK --- FTN Ticker / Request Processor
3 *****************************************************************************
4 * Filelist generator routines.
5 *
6 * This file is part of HTICK, part of the Husky fidosoft project
7 * http://husky.sf.net
8 *
9 * HTICK is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2, or (at your option) any
12 * later version.
13 *
14 * HTICK is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with HTICK; see the file COPYING. If not, write to the Free
21 * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *****************************************************************************
23 * $Id$
24 *****************************************************************************/
25
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32
33
34 #include <huskylib/huskylib.h>
35
36 #include <huskylib/log.h>
37 #include <huskylib/dirlayer.h>
38 #include <huskylib/xstr.h>
39
40 #include <fidoconf/common.h>
41 #include <fidoconf/afixcmd.h>
42
43 #include <areafix/areafix.h>
44
45 #include "add_desc.h"
46 #include "global.h"
47 #include "fcommon.h"
48 #include "filelist.h"
49 #include "toss.h"
50
51 typedef struct _FileDescEntry
52 {
53 char *filename;
54 char **desc; /* Short Description of file */
55 UINT anzdesc; /* Number of Desc Lines */
56 } FileDescEntry;
57
58
59 static BigSize totalfilessize;
60 unsigned int totalfilesnumber = 0;
61 static tree *DescTree = NULL;
62 static FileDescEntry fdesccmp;
63 char *DescNA = "Description not avaliable";
64
DescTreeDeleteEntry(char * entry)65 int DescTreeDeleteEntry( char *entry )
66 {
67 if( entry )
68 {
69 FileDescEntry *entxt;
70 UINT i;
71
72 entxt = ( FileDescEntry * ) entry;
73 nfree( entxt->filename );
74 for( i = 0; i < entxt->anzdesc; i++ )
75 nfree( entxt->desc[i] );
76 nfree( entxt->desc );
77 nfree( entxt );
78 }
79 return 1;
80 }
81
DescTreeCompareEntries(char * p_e1,char * p_e2)82 int DescTreeCompareEntries( char *p_e1, char *p_e2 )
83 {
84 FileDescEntry *e1 = ( FileDescEntry * ) p_e1;
85 FileDescEntry *e2 = ( FileDescEntry * ) p_e2;
86
87 if( !p_e1 || !p_e2 )
88 {
89 w_log( LL_CRIT,
90 __FILE__
91 ":: Parameter is NULL: DescTreeCompareEntries(%s,%s). This is serious error in program, please report to developers.",
92 p_e1 ? "p_e1" : "NULL", p_e2 ? "p_e2" : "NULL" );
93 return -1;
94 }
95
96 return strcmp( e1->filename, e2->filename );
97 }
98
99
ParseBBSFile(const char * fbbsname)100 int ParseBBSFile( const char *fbbsname )
101 {
102 FILE *filehandle;
103 char *line = NULL, *tmp = NULL, *token = NULL, *p = NULL;
104 int flag = 0, rc = 1;
105 FileDescEntry *fdesc = NULL;
106
107 if( !fbbsname )
108 {
109 w_log( LL_CRIT,
110 __FILE__
111 ":: Parameter is NULL: ParseBBSFile(%s). This is serious error in program, please report to developers.",
112 fbbsname ? "fbbsname" : "NULL" );
113 return -1;
114 }
115
116 if( DescTree )
117 {
118 tree_mung( &DescTree, DescTreeDeleteEntry );
119 }
120 tree_init( &DescTree, 1 );
121
122
123 filehandle = fopen( fbbsname, "r+b" );
124 if( filehandle == NULL )
125 return 1;
126
127 while( ( line = readLine( filehandle ) ) != NULL )
128 {
129
130 if( flag && ( *line == '\t' || *line == ' ' || *line == '>' ) )
131 {
132 token = stripLeadingChars( line, " >" );
133 if( *token == '>' )
134 token++;
135 fdesc->desc = srealloc( fdesc->desc, ( fdesc->anzdesc + 1 ) * sizeof( *fdesc->desc ) );
136 fdesc->desc[fdesc->anzdesc] = sstrdup( token );
137 fdesc->anzdesc++;
138 nfree( line );
139 continue;
140 }
141 else
142 {
143 flag = 0;
144 if( rc == 0 )
145 {
146 tree_add( &DescTree, DescTreeCompareEntries, ( char * )fdesc, DescTreeDeleteEntry );
147 }
148 }
149 tmp = sstrdup( line );
150 token = tmp;
151 p = token;
152 while( p && *p != '\0' && !isspace( *p ) )
153 p++;
154 if( p && *p != '\0' )
155 {
156 *p = '\0';
157 }
158 else
159 {
160 p = NULL;
161 }
162
163 fdesc = scalloc( 1, sizeof( FileDescEntry ) );
164 fdesc->filename = sstrdup( token );
165
166 if( p == NULL )
167 {
168 token = "";
169 }
170 else
171 {
172 p++;
173 while( p && *p != '\0' && isspace( *p ) )
174 p++;
175 if( p && *p != '\0' )
176 token = p;
177 else
178 token = "";
179 }
180 if( config->addDLC && config->DLCDigits > 0 && config->DLCDigits < 10 && token[0] == '[' )
181 {
182 while( ']' != *p )
183 p++;
184 p++;
185 while( p && !isspace( *p ) )
186 p++;
187 token = p;
188 }
189 fdesc->anzdesc = 0;
190 fdesc->desc = srealloc( fdesc->desc, ( fdesc->anzdesc + 1 ) * sizeof( *fdesc->desc ) );
191 fdesc->desc[fdesc->anzdesc] = sstrdup( token );
192 fdesc->anzdesc++;
193 flag = 1;
194 rc = 0;
195 nfree( line );
196 nfree( tmp );
197 }
198 if( rc == 0 )
199 {
200 tree_add( &DescTree, DescTreeCompareEntries, ( char * )fdesc, DescTreeDeleteEntry );
201 }
202 fclose( filehandle );
203 return rc;
204 }
205
putFileInFilelist(FILE * f,char * filename,off_t size,int day,int month,int year,int countdesc,char ** desc)206 void putFileInFilelist( FILE * f, char *filename, off_t size, int day, int month, int year,
207 int countdesc, char **desc )
208 {
209 int i;
210 static BigSize bs;
211
212 if( !f || !filename || !desc )
213 {
214 w_log( LL_CRIT,
215 __FILE__
216 ":: Parameter is NULL: putFileInFilelist(%s,%s,size,day,month,year,countdesc,%s). This is serious error in program, please report to developers.",
217 f ? "f" : "NULL", filename ? "filename" : "NULL", desc ? "desc" : "NULL" );
218 return;
219 }
220
221 memset( &bs, 0, sizeof( BigSize ) );
222 IncBigSize( &bs, ( ULONG ) size );
223 fprintf( f, "%-12s", filename );
224 fprintf( f, "%8s ", PrintBigSize( &bs ) );
225 fprintf( f, "%02u-", day );
226
227 switch ( month )
228 {
229 case 0:
230 fprintf( f, "Jan" );
231 break;
232 case 1:
233 fprintf( f, "Feb" );
234 break;
235 case 2:
236 fprintf( f, "Mar" );
237 break;
238 case 3:
239 fprintf( f, "Apr" );
240 break;
241 case 4:
242 fprintf( f, "May" );
243 break;
244 case 5:
245 fprintf( f, "Jun" );
246 break;
247 case 6:
248 fprintf( f, "Jul" );
249 break;
250 case 7:
251 fprintf( f, "Aug" );
252 break;
253 case 8:
254 fprintf( f, "Sep" );
255 break;
256 case 9:
257 fprintf( f, "Oct" );
258 break;
259 case 10:
260 fprintf( f, "Nov" );
261 break;
262 case 11:
263 fprintf( f, "Dec" );
264 break;
265 default:
266 break;
267 }
268 fprintf( f, "-%02u", year % 100 );
269 if( countdesc == 0 )
270 fprintf( f, " Description not avaliable\n" );
271 else
272 {
273 /* desc = formatDesc(desc, &countdesc); */
274 for( i = 0; i < countdesc; i++ )
275 {
276 if( desc[i] )
277 {
278 if( i == 0 )
279 fprintf( f, " %s\n", desc[i] );
280 else
281 fprintf( f, " %s\n", desc[i] );
282 }
283 else
284 {
285 w_log( LL_CRIT,
286 __FILE__
287 "::putFileInFilelist() Description line %i is NULL. This is serious error in program, please report to developers.",
288 i );
289 break;
290 }
291 }
292 }
293 return;
294 }
295
printFileArea(char * area_areaName,char * area_pathName,char * area_description,FILE * f,int bbs)296 void printFileArea( char *area_areaName, char *area_pathName, char *area_description, FILE * f,
297 int bbs )
298 {
299
300 char *fileareapath = NULL, *fbbsname = NULL, *filename = NULL;
301 char *fbbsline;
302 husky_DIR *dir;
303 char *file;
304 struct stat stbuf;
305 FileDescEntry *fdesc;
306 time_t fileTime;
307 struct tm *locTime;
308 unsigned int totalnumber = 0;
309 char **removeFiles = NULL;
310 unsigned int removeCount = 0, i, Len;
311 FILE *fbbs;
312 char *token = "";
313 int flag = 0;
314 static BigSize bs;
315
316 if( !area_areaName || !area_pathName || !f )
317 {
318 w_log( LL_CRIT,
319 __FILE__
320 ":: Parameter is NULL: printFileArea(%s,%s,%s,%s). This is serious error in program, please report to developers.",
321 area_areaName ? "area_areaName" : "NULL", area_pathName ? "area_pathName" : "NULL",
322 "area_description", f ? "f" : "NULL" );
323 return;
324 }
325
326 memset( &bs, 0, sizeof( BigSize ) );
327
328 fileareapath = sstrdup( area_pathName );
329 adaptcase( fileareapath );
330 xstrscat( &fbbsname, fileareapath, config->fileDescription, NULL );
331 adaptcase( fbbsname );
332
333 dir = husky_opendir( fileareapath );
334 if( dir == NULL )
335 return;
336
337 w_log( LL_INFO, "Processing: %s", area_areaName );
338
339 ParseBBSFile( fbbsname );
340
341 while( ( file = husky_readdir( dir ) ) != NULL )
342 {
343 if( strcmp( file, "." ) == 0 || strcmp( file, ".." ) == 0 )
344 continue;
345 nfree( filename );
346 xstrscat( &filename, fileareapath, file, NULL );
347 if( stricmp( filename, fbbsname ) == 0 )
348 continue;
349 if( direxist( filename ) )
350 continue;
351 if( !flag )
352 {
353 if( bbs )
354 fprintf( f, "BbsArea: %s", area_areaName );
355 else
356 fprintf( f, "FileArea: %s", area_areaName );
357 if( area_description != NULL )
358 fprintf( f, " (%s)\n", area_description );
359 else
360 fprintf( f, "\n" );
361 fprintf( f,
362 "-----------------------------------------------------------------------------\n" );
363 flag = 1;
364 }
365 fdesccmp.filename = file;
366 fdesc =
367 ( FileDescEntry * ) tree_srch( &DescTree, DescTreeCompareEntries, ( char * )( &fdesccmp ) );
368 if( !fdesc )
369 {
370 add_description( fbbsname, file, &DescNA, 1 );
371 }
372 stat( filename, &stbuf );
373 fileTime = stbuf.st_mtime > 0 ? stbuf.st_mtime : 0;
374 locTime = localtime( &fileTime );
375 IncBigSize( &bs, ( ULONG ) stbuf.st_size );
376 totalnumber++;
377 if( fdesc )
378 {
379 putFileInFilelist( f, file, stbuf.st_size, locTime->tm_mday, locTime->tm_mon,
380 locTime->tm_year, fdesc->anzdesc, fdesc->desc );
381 }
382 else
383 {
384 putFileInFilelist( f, file, stbuf.st_size, locTime->tm_mday, locTime->tm_mon,
385 locTime->tm_year, 1, &DescNA );
386 }
387 }
388 husky_closedir( dir );
389 if( flag )
390 {
391 fprintf( f, "-----------------------------------------------------------------------------\n" );
392 fprintf( f, "Total files in area: %6d, total size: %10s bytes\n\n", totalnumber,
393 PrintBigSize( &bs ) );
394 }
395
396 /* collect information about files in files.bbs that realy do not exist */
397 if( ( fbbs = fopen( fbbsname, "r" ) ) == NULL )
398 return;
399 while( ( fbbsline = readLine( fbbs ) ) != NULL )
400 {
401 if( *fbbsline == 0 || *fbbsline == 10 || *fbbsline == 13
402 || *fbbsline == ' ' || *fbbsline == '\t' || *fbbsline == '>' )
403 continue;
404
405 Len = strlen( fbbsline );
406 if( fbbsline[Len - 1] == '\n' )
407 fbbsline[--Len] = 0;
408
409 if( fbbsline[Len - 1] == '\r' )
410 fbbsline[--Len] = 0;
411
412 token = strtok( fbbsline, " \t\0" );
413
414 if( token == NULL )
415 continue;
416 nfree( filename );
417 xstrscat( &filename, fileareapath, token, NULL );
418 adaptcase( filename );
419 if( !fexist( filename ) )
420 {
421 removeFiles = srealloc( removeFiles, sizeof( char * ) * ( removeCount + 1 ) );
422 removeFiles[removeCount] =
423 ( char * )smalloc( strlen( strrchr( filename, PATH_DELIM ) + 1 ) + 1 );
424 strcpy( removeFiles[removeCount], strrchr( filename, PATH_DELIM ) + 1 );
425 removeCount++;
426 }
427 nfree( fbbsline );
428 }
429 fclose( fbbs );
430
431 /* remove descriptions from files.bbs on files that realy do not exist */
432 if( removeCount > 0 )
433 {
434 for( i = 0; i < removeCount; i++ )
435 {
436 removeDesc( fbbsname, removeFiles[i] );
437 nfree( removeFiles[i] );
438 }
439 nfree( removeFiles );
440 }
441 IncBigSize2( &totalfilessize, &bs );
442 totalfilesnumber += totalnumber;
443 nfree( filename );
444 return;
445 }
446
filelist()447 void filelist( )
448 {
449 FILE *f = NULL;
450 FILE *d = NULL;
451 unsigned int i;
452
453 w_log( LL_INFO, "Start filelist..." );
454
455 if( flistfile == NULL )
456 {
457 w_log( '6', "Could not find output file" );
458 return;
459 }
460
461 if( ( f = fopen( flistfile, "w" ) ) == NULL )
462 {
463 w_log( '6', "Could not open for write file %s", flistfile );
464 return;
465 }
466
467 if( dlistfile )
468 {
469 if( ( d = fopen( dlistfile, "w" ) ) == NULL )
470 {
471 w_log( '6', "Could not open for write file %s", dlistfile );
472 }
473 }
474 for( i = 0; i < config->fileAreaCount; i++ )
475 {
476 if( config->fileAreas[i].msgbType != MSGTYPE_PASSTHROUGH && !( config->fileAreas[i].hide ) )
477 {
478 printFileArea( config->fileAreas[i].areaName, config->fileAreas[i].fileName,
479 config->fileAreas[i].description, f, 0 );
480 if( d )
481 fprintf( d, "%s\n", config->fileAreas[i].fileName );
482 }
483 }
484
485 for( i = 0; i < config->bbsAreaCount; i++ )
486 {
487 printFileArea( config->bbsAreas[i].areaName, config->bbsAreas[i].pathName,
488 config->bbsAreas[i].description, f, 1 );
489 if( d )
490 fprintf( d, "%s\n", config->bbsAreas[i].pathName );
491 }
492
493 fprintf( f, "=============================================================================\n" );
494 fprintf( f, "Total files in filelist: %6d, total size: %10s bytes\n", totalfilesnumber,
495 PrintBigSize( &totalfilessize ) );
496 fprintf( f, "=============================================================================\n\n" );
497
498 fclose( f );
499 if( d )
500 fclose( d );
501 }
502