1 /*****************************************************************************
2  * HTICK --- FTN Ticker / Request Processor
3  *****************************************************************************
4  * This file is part of HTICK, part of the Husky fidosoft project
5  * http://husky.physcip.uni-stuttgart.de
6  *
7  * HTICK is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the
9  * Free Software Foundation; either version 2, or (at your option) any
10  * later version.
11  *
12  * HTICK is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with HTICK; see the file COPYING.  If not, write to the Free
19  * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20  *****************************************************************************
21  * $Id$
22  *****************************************************************************/
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <ctype.h>
27 #include <string.h>
28 #include <errno.h>
29 
30 #include <huskylib/compiler.h>
31 
32 #ifdef HAS_PROCESS_H
33 # include <process.h>
34 #endif
35 
36 #ifdef HAS_DOS_H
37 # include <dos.h>
38 #endif
39 
40 #if HAS_UNISTD_H
41 # include <unistd.h>
42 #endif
43 
44 #include <huskylib/huskylib.h>
45 
46 #include <fidoconf/fidoconf.h>
47 #include <fidoconf/common.h>
48 #include <huskylib/recode.h>
49 #include <huskylib/xstr.h>
50 #include <huskylib/dirlayer.h>
51 #include <areafix/areafix.h>    /* for print_ch() */
52 
53 #ifdef USE_HPTZIP
54 # include <hptzip/hptzip.h>
55 #endif
56 
57 
58 #include <add_desc.h>
59 #include <global.h>
60 #include <toss.h>
61 #include <filecase.h>
62 
63 /*  Return:
64  * 0 if success
65  * 1 if error
66  * -1 if ivalid parameter
67  */
add_description(char * descr_file_name,char * file_name,char ** description,unsigned int count_desc)68 int add_description( char *descr_file_name, char *file_name, char **description,
69                      unsigned int count_desc )
70 {
71   FILE *descr_file;
72   unsigned int i;
73   char *desc_line = NULL;
74   char *namefile = NULL;
75   int descOnNewLine = 0;
76 
77   if( !descr_file_name || !file_name || !description )
78   {
79     w_log( LL_CRIT,
80            __FILE__
81            ":: Parameter is NULL: add_description(%s,%s,%s,count_desc). This is serious error in program, please report to developers.",
82            descr_file_name ? "descr_file_name" : "NULL", file_name ? "file_name" : "NULL",
83            description ? "description" : "NULL" );
84     return -1;
85   }
86   for( i = 0; i < count_desc; i++ )
87   {
88     if( !description[i] )
89     {
90       w_log( LL_CRIT,
91              __FILE__
92              "::add_description(...,description,%i) Array in parameter has NULL element: description[%i]. This is serious error in program, please report to developers.",
93              count_desc, i );
94       return -1;
95     }
96   }
97 
98   descr_file = fopen( descr_file_name, "a" );
99   if( descr_file == NULL )
100     return 1;
101 
102   namefile = sstrdup( file_name );
103 
104   MakeProperCase( namefile );
105   xscatprintf( &desc_line, "%-12s", namefile );
106   /* fprintf (descr_file, "%-12s", namefile); */
107   if( config->addDLC && config->DLCDigits > 0 && config->DLCDigits < 10 )
108   {
109     char dlc[10];
110 
111     dlc[0] = ' ';
112     dlc[1] = '[';
113     for( i = 1; i <= config->DLCDigits; i++ )
114       dlc[i + 1] = '0';
115     dlc[i + 1] = ']';
116     dlc[i + 2] = '\x00';
117     /* fprintf (descr_file, "%s", dlc); */
118     xstrcat( &desc_line, dlc );
119   }
120   if( ( strlen( namefile ) > 12 ) && ( strlen( desc_line ) + strlen( description[0] ) > 78 ) )
121   {
122     fprintf( descr_file, "%s\n", desc_line );
123     descOnNewLine = 1;
124   }
125   else
126   {
127     fprintf( descr_file, "%s", desc_line );
128   }
129   for( i = 0; i < count_desc; i++ )
130   {
131     desc_line = sstrdup( description[i] );
132     if( config->intab != NULL )
133       recodeToInternalCharset( desc_line );
134     if( descOnNewLine == 0 )
135     {
136       fprintf( descr_file, " %s\n", desc_line );
137       descOnNewLine = 1;
138     }
139     else
140     {
141       if( config->fileDescPos == 0 )
142         config->fileDescPos = 1;
143       fprintf( descr_file, "%s%s%s\n", print_ch( config->fileDescPos - 1, ' ' ),
144                ( config->fileLDescString == NULL ) ? " " : config->fileLDescString, desc_line );
145 
146     }
147     nfree( desc_line );
148   }
149   if( count_desc == 0 )
150     fprintf( descr_file, "\n" );
151   fclose( descr_file );
152   nfree( namefile );
153   return 0;
154 }
155 
156 /*  Return:
157  * 0 if success
158  * 1 if error
159  * -1 if ivalid parameter
160  */
removeDesc(char * descr_file_name,char * file_name)161 int removeDesc( char *descr_file_name, char *file_name )
162 {
163   FILE *f1, *f2;
164   char *line, *tmp, *token, *descr_file_name_tmp, *LDescString;
165   int flag = 0;
166 
167   if( !descr_file_name || !file_name )
168   {
169     w_log( LL_CRIT,
170            __FILE__
171            ":: Parameter is NULL: removeDesc(%s,%s). This is serious error in program, please report to developers.",
172            descr_file_name ? "descr_file_name" : "NULL", file_name ? "file_name" : "NULL" );
173     return -1;
174   }
175 
176   line = tmp = token = descr_file_name_tmp = LDescString = NULL;
177   f1 = fopen( descr_file_name, "r" );
178   if( f1 == NULL )
179     return 1;
180 
181   /* strcpy(descr_file_name_tmp,descr_file_name); */
182   /* strcat(descr_file_name_tmp,".tmp"); */
183 
184   xstrscat( &descr_file_name_tmp, descr_file_name, ".tmp", NULL );
185 
186   f2 = fopen( descr_file_name_tmp, "w" );
187   if( f2 == NULL )
188   {
189     fclose( f1 );
190     nfree( descr_file_name_tmp );
191     return 1;
192   }
193 
194   if( config->fileLDescString == NULL )
195     LDescString = sstrdup( ">" );
196   else
197     LDescString = sstrdup( config->fileLDescString );
198 
199   while( ( line = readLine( f1 ) ) != NULL )
200   {
201     if( *line == 0 || *line == 10 || *line == 13 )
202       continue;
203 
204     if( line[strlen( line ) - 1] == '\r' )
205       line[strlen( line ) - 1] = 0;
206 
207     if( flag && ( *line == '\t' || *line == ' ' || *line == *LDescString ) )
208       continue;
209     else
210       flag = 0;
211 
212     tmp = sstrdup( line );
213     token = strtok( tmp, " \t\0" );
214 
215     if( token != NULL )
216     {
217       if( stricmp( token, file_name ) != 0 )
218       {
219         fputs( line, f2 );
220         fputs( "\n", f2 );
221       }
222       else
223         flag = 1;
224     }
225     nfree( tmp );
226     nfree( line );
227   }
228 
229   nfree( LDescString );
230   fclose( f1 );
231   fclose( f2 );
232   move_file( descr_file_name_tmp, descr_file_name, 1 ); /* overwrite old file */
233   nfree( descr_file_name_tmp );
234   return 0;
235 }
236 
237 /*  Return:
238  * 0 if success
239  * 1 if error
240  * -1 if ivalid parameter
241  */
announceNewFileecho(char * announcenewfileecho,char * c_area,char * hisaddr)242 int announceNewFileecho( char *announcenewfileecho, char *c_area, char *hisaddr )
243 {
244   FILE *ann_file;
245 
246   if( !announcenewfileecho || !c_area || !hisaddr )
247   {
248     w_log( LL_CRIT,
249            __FILE__
250            ":: Parameter is NULL: announceNewFileecho(%s,%s,%s). This is serious error in program, please report to developers.",
251            announcenewfileecho ? "announcenewfileecho" : "NULL", c_area ? "c_area" : "NULL",
252            hisaddr ? "hisaddr" : "NULL" );
253     return -1;
254   }
255 
256   if( !fexist( announcenewfileecho ) )
257   {
258     ann_file = fopen( announcenewfileecho, "w" );
259     if( ann_file == NULL )
260       return 1;
261     fprintf( ann_file, "Action   Name                                                 By\n" );
262     fprintf( ann_file,
263              "-------------------------------------------------------------------------------\n" );
264   }
265   else
266   {
267     ann_file = fopen( announcenewfileecho, "a" );
268     if( ann_file == NULL )
269       return 1;
270   }
271   fprintf( ann_file, "Created  %-52s %s\n", c_area, hisaddr );
272   fclose( ann_file );
273   return 0;
274 }
275 
276 /*  Return:
277  * 0 if success
278  * 1 if error
279  * -1 if ivalid parameter
280  */
GetDescFormBbsFile(char * descr_file_name,char * file_name,s_ticfile * tic)281 int GetDescFormBbsFile( char *descr_file_name, char *file_name, s_ticfile * tic )
282 {
283   FILE *filehandle;
284   char *line = NULL, *tmp = NULL, *token = NULL;
285   char *p = token;
286   int flag = 0, rc = 1;
287 
288   if( !descr_file_name || !file_name || !tic )
289   {
290     w_log( LL_CRIT,
291            __FILE__
292            ":: Parameter is NULL: GetDescFormBbsFile(%s,%s,%s). This is serious error in program, please report to developers.",
293            descr_file_name ? "descr_file_name" : "NULL", file_name ? "file_name" : "NULL",
294            tic ? "tic" : "NULL" );
295     return -1;
296   }
297 
298   filehandle = fopen( descr_file_name, "r+b" );
299   if( filehandle == NULL )
300     return 1;
301 
302   while( ( line = readLine( filehandle ) ) != NULL )
303   {
304 
305     if( flag && ( *line == '\t' || *line == ' ' || *line == '>' ) )
306     {
307       token = stripLeadingChars( line, " >" );
308       if( *token == '>' )
309         token++;
310       tic->desc = srealloc( tic->desc, ( tic->anzdesc + 1 ) * sizeof( *tic->desc ) );
311       tic->desc[tic->anzdesc] = sstrdup( token );
312       tic->anzdesc++;
313       nfree( line );
314       continue;
315     }
316     else
317     {
318       if( rc == 0 )
319       {
320         nfree( line );
321         break;
322       }
323       else
324         flag = 0;
325     }
326     tmp = sstrdup( line );
327     token = tmp;
328     p = token;
329     while( p && *p != '\0' && !isspace( *p ) )
330       p++;
331     if( p && *p != '\0' )
332       *p = '\0';
333     else
334       p = NULL;
335 
336     if( stricmp( token, file_name ) == 0 )
337     {
338       UINT i;
339 
340       if( p == NULL )
341       {
342         token = "";
343       }
344       else
345       {
346         p++;
347         while( p && *p != '\0' && isspace( *p ) )
348           p++;
349         if( p && *p != '\0' )
350           token = p;
351         else
352           token = "";
353       }
354       if( config->addDLC && config->DLCDigits > 0 && config->DLCDigits < 10 && token[0] == '[' )
355       {
356         while( ']' != *p )
357           p++;
358         p++;
359         while( p && !isspace( *p ) )
360           p++;
361         token = p;
362       }
363       for( i = 0; i < tic->anzdesc; i++ )
364         nfree( tic->desc[i] );
365       tic->anzdesc = 0;
366       tic->desc = srealloc( tic->desc, ( tic->anzdesc + 1 ) * sizeof( *tic->desc ) );
367       tic->desc[tic->anzdesc] = sstrdup( token );
368       tic->anzdesc++;
369       flag = 1;
370       rc = 0;
371     }
372     nfree( line );
373     nfree( tmp );
374   }
375 
376   fclose( filehandle );
377   w_log( LL_FILE, "getDesc OK for file: %s", file_name );
378   return rc;
379 }
380 
381 /*  Return:
382  * 0 if description is not set
383  * 1 if description is set from specified file
384  * 3 if error opening file
385  * -1 if ivalid parameter
386  */
GetDescFormFile(char * fileName,s_ticfile * tic)387 int GetDescFormFile( char *fileName, s_ticfile * tic )
388 {
389   FILE *filehandle = NULL;
390   UINT i;
391   char *line = NULL;
392 
393   if( !fileName || !tic )
394   {
395     w_log( LL_CRIT,
396            __FILE__
397            ":: Parameter is NULL: GetDescFormFile(%s,%s). This is serious error in program, please report to developers.",
398            fileName ? "fileName" : "NULL", tic ? "tic" : "NULL" );
399     return -1;
400   }
401 
402   if( ( filehandle = fopen( fileName, "r" ) ) == NULL )
403   {
404     w_log( LL_ERROR, "Error at opening file \"%s\": %s", fileName, strerror( errno ) );
405     return 3;
406   };
407 
408   for( i = 0; i < tic->anzldesc; i++ )
409     nfree( tic->ldesc[i] );
410   tic->anzldesc = 0;
411 
412   while( ( line = readLine( filehandle ) ) != NULL )
413   {
414     tic->ldesc = srealloc( tic->ldesc, ( tic->anzldesc + 1 ) * sizeof( *tic->ldesc ) );
415     tic->ldesc[tic->anzldesc] = sstrdup( line );
416     tic->anzldesc++;
417     nfree( line );
418   }                             /* endwhile */
419   fclose( filehandle );
420   return tic->anzldesc ? 1 : 0;
421 }
422 
423 /*  Return:
424  * 1 if description is set from  description file ("file_id.diz" from archive)
425  * 0 if description not set
426  * -1 if ivalid parameter
427  * 2 if error opening file
428  * 3 if unpacker not found for this file or all diz-files don't unpacked
429  */
GetDescFormDizFile(char * fileName,s_ticfile * tic)430 int GetDescFormDizFile( char *fileName, s_ticfile * tic )
431 {
432   FILE *filehandle = NULL;
433   char *dizfile = NULL;
434   int j, found;
435   UINT i, unpacker;
436   signed int cmdexit;
437   char cmd[256] = "";
438   char buffer[256] = "";
439 
440   if( !fileName || !tic )
441   {
442     w_log( LL_CRIT,
443            __FILE__
444            ":: Parameter is NULL: GetDescFormFile(%s,%s). This is serious error in program, please report to developers.",
445            fileName ? "fileName" : "NULL", tic ? "tic" : "NULL" );
446     return -1;
447   }
448 
449   /*  find what unpacker to use */
450   for( i = 0, found = 0; ( i < config->unpackCount ) && !found; i++ )
451   {
452     filehandle = fopen( fileName, "rb" );
453     if( filehandle == NULL )
454       return 2;
455     /*  is offset is negative we look at the end */
456     fseek( filehandle, config->unpack[i].offset,
457            config->unpack[i].offset >= 0 ? SEEK_SET : SEEK_END );
458     if( ferror( filehandle ) )
459     {
460       fclose( filehandle );
461       continue;
462     };
463     for( found = 1, j = 0; j < config->unpack[i].codeSize; j++ )
464     {
465       if( ( getc( filehandle ) & config->unpack[i].mask[j] ) != config->unpack[i].matchCode[j] )
466         found = 0;
467     }
468     fclose( filehandle );
469   }
470 
471   if( found == 0 )
472   {
473     w_log( LL_ALERT, "file %s: cannot find unpacker", fileName );
474     return 3;
475   }
476   unpacker = i - 1;
477   getcwd( buffer, 256 );
478   /*  unpack file_id.diz (config->fileDescName) */
479   for( i = 0; i < config->fDescNameCount; i++ )
480   {
481     fillCmdStatement( cmd, config->unpack[unpacker].call, fileName, config->fileDescNames[i],
482                       config->tempInbound );
483     w_log( LL_EXEC, "File %s: unpacking with \"%s\"", fileName, cmd );
484     chdir( config->tempInbound );
485     if( fc_stristr( config->unpack[unpacker].call, ZIPINTERNAL ) )
486     {
487 #ifdef USE_HPTZIP
488       cmdexit = UnPackWithZlib( fileName, config->fileDescNames[i], config->tempInbound );
489 #else
490       cmdexit = 0;
491       w_log( LL_ERROR,
492              "\"%s\" don't implemented in this build (disabled at compile time). Please use your unzip program.",
493              ZIPINTERNAL );
494       continue;
495 #endif
496     }
497     else
498     {
499       cmdexit = cmdcall( cmd );
500     }
501 
502     chdir( buffer );
503 
504     if( cmdexit != 0 )
505     {
506       w_log( LL_ERROR, "exec failed, code %d", cmdexit );
507       continue;
508     }
509 
510     xscatprintf( &dizfile, "%s%s", config->tempInbound, config->fileDescNames[i] );
511 
512     if( fexist( dizfile ) )
513       found = GetDescFormFile( dizfile, tic );
514 
515     if( found == 1 )
516     {
517       remove( dizfile );
518       i = config->fDescNameCount;
519     }
520     nfree( dizfile );
521   }
522   return found;
523 }
524