1 /*
2 *
3 * XASTIR, Amateur Station Tracking and Information Reporting
4 * Copyright (C) 1999,2000 Frank Giannandrea
5 * Copyright (C) 2000-2019 The Xastir Group
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 *
21 * Look at the README for more information on the program.
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif // HAVE_CONFIG_H
27
28 #include "snprintf.h"
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <ctype.h>
34
35 #if TIME_WITH_SYS_TIME
36 #include <sys/time.h>
37 #include <time.h>
38 #else // TIME_WITH_SYS_TIME
39 #if HAVE_SYS_TIME_H
40 #include <sys/time.h>
41 #else // HAVE_SYS_TIME_H
42 #include <time.h>
43 #endif // HAVE_SYS_TIME_H
44 #endif // TIME_WITH_SYS_TIME
45
46 #include <Xm/XmAll.h>
47
48 #include "xastir.h"
49 #include "fcc_data.h"
50 #include "xa_config.h"
51 #include "main.h"
52
53 // Must be last include file
54 #include "leak_detection.h"
55
56
57
58
59
call_only(char * callsign)60 char *call_only(char *callsign)
61 {
62 int i, len;
63
64 len = strlen(callsign);
65 for (i = 0; i < len; i++)
66 {
67 if (!isalnum((int)callsign[i]))
68 {
69 callsign[i]='\0';
70 i=len;
71 }
72 }
73 return(callsign);
74 }
75
76
77
78
79
80 /* ==================================================================== */
81 /* build a new (or newer if I check the file date) index file */
82 /* check for current ic index file */
83 /* FG: added a date check in case the FCC file has been updated. */
84 /* appl.dat must have a time stamp newer than the index file time */
85 /* stamp. Use the touch command on the appl.dat file to make the */
86 /* time current if necessary. */
87 // How this works: The index file contains a few callsigns and their
88 // offsets into the large database file. The code uses these as
89 // jump-off points to look for a particular call, to speed things up.
90 /* ******************************************************************** */
build_fcc_index(int type)91 int build_fcc_index(int type)
92 {
93 FILE *fdb;
94 FILE *fndx;
95 unsigned long call_offset = 0;
96 unsigned long x = 0;
97 char fccdata[FCC_DATA_LEN+8];
98 char database_name[100];
99 int found,i,num;
100 char appl_file_path[MAX_VALUE];
101
102 if (type==1)
103 {
104 xastir_snprintf(database_name, sizeof(database_name), "fcc/appl.dat");
105 }
106 else
107 {
108 xastir_snprintf(database_name, sizeof(database_name), "fcc/EN.dat");
109 }
110
111 /* ==================================================================== */
112 /* If the index file is there, exit */
113 /* */
114 get_user_base_dir("data/appl.ndx", appl_file_path,
115 sizeof(appl_file_path));
116 if (filethere(appl_file_path))
117 {
118 /* if file is there make sure the index date is newer */
119 if (file_time(get_data_base_dir(database_name))<=file_time(appl_file_path))
120 {
121 return(1);
122 }
123 else
124 {
125 // FCC index old, rebuilding
126 statusline(langcode("STIFCC0100"),1);
127
128 fprintf(stderr,"FCC index is old. Rebuilding index.\n");
129 // XmTextFieldSetString(text,"FCC index old, rebuilding");
130 // XtManageChild(text);
131 // XmUpdateDisplay(XtParent(text)); // DK7IN: do we need this ???
132 }
133 }
134
135 /* ==================================================================== */
136 /* Open the database and index file */
137 /* */
138 fdb=fopen(get_data_base_dir(database_name),"rb");
139 if (fdb==NULL)
140 {
141 fprintf(stderr,"Build:Could not open FCC data base: %s\n", get_data_base_dir(database_name) );
142 return(0);
143 }
144
145 fndx=fopen(appl_file_path,"w");
146 if (fndx==NULL)
147 {
148 fprintf(stderr,"Build:Could not open/create FCC data base index: %s\n", appl_file_path );
149 (void)fclose(fdb);
150 return(0);
151 }
152
153 /* ==================================================================== */
154 /* write out the current callsign and RBA of the db file */
155 /* skip (index_skip) records and do it again until no more */
156 /* */
157 xastir_snprintf(fccdata,sizeof(fccdata)," ");
158 while(!feof(fdb))
159 {
160 call_offset = (unsigned long)ftell(fdb);
161 if (fgets(fccdata, (int)sizeof(fccdata), fdb) == NULL)
162 {
163 // error occurred
164 fprintf(stderr,"Build: Could not read fcc data base: %s \n", appl_file_path);
165 (void)fclose(fdb);
166 return(0);
167 }
168 found=0;
169 num=0;
170 if (type==2)
171 {
172 for(i=0; i<14 && !found; i++)
173 {
174 if(fccdata[i]=='|')
175 {
176 num++;
177 if(num==4)
178 {
179 found=i+1;
180 }
181 }
182 }
183 }
184 (void)call_only(fccdata+found);
185 fprintf(fndx,"%-6.6s%li\n",fccdata+found,call_offset+found);
186 for (x=0; x<=500 && !feof(fdb); x++)
187 {
188 if (fgets(fccdata, (int)sizeof(fccdata), fdb)==NULL)
189 {
190 break;
191 }
192 }
193 }
194 (void)fclose(fdb);
195 (void)fclose(fndx);
196
197 // XmTextFieldSetString(text,"");
198 // XtManageChild(text);
199
200 return(1);
201 }
202
203
204
205
206
207 /* ==================================================================== */
208 /* Check for ic data base file */
209 /* Check/build the index */
210 /* */
211 /* ******************************************************************** */
check_fcc_data(void)212 int check_fcc_data(void)
213 {
214 int fcc_data_available = 0;
215 if (filethere(get_data_base_dir("fcc/EN.dat")) && filethere(get_data_base_dir("fcc/appl.dat")))
216 {
217 if(file_time(get_data_base_dir("fcc/appl.dat"))<=file_time(get_data_base_dir("fcc/EN.dat")))
218 {
219 /*fprintf(stderr,"NEW FORMAT FCC DATA FILE is NEWER THAN OLD FCC FORMAT\n");*/
220 if (build_fcc_index(2))
221 {
222 fcc_data_available=2;
223 }
224 else
225 {
226 fprintf(stderr,"Check:Could not build fcc data base index\n");
227 fcc_data_available=0;
228 }
229 }
230 else
231 {
232 /*fprintf(stderr,"OLD FORMAT FCC DATA FILE is NEWER THAN NEW FCC FORMAT\n");*/
233 if (build_fcc_index(1))
234 {
235 fcc_data_available=1;
236 }
237 else
238 {
239 fprintf(stderr,"Check:Could not build fcc data base index\n");
240 fcc_data_available=0;
241 }
242 }
243 }
244 else
245 {
246 if (filethere(get_data_base_dir("fcc/EN.dat")))
247 {
248 /*fprintf(stderr,"NO OLD FCC, BUT NEW FORMAT FCC DATA AVAILABLE\n");*/
249 if (build_fcc_index(2))
250 {
251 fcc_data_available=2;
252 }
253 else
254 {
255 fprintf(stderr,"Check:Could not build fcc data base index\n");
256 fcc_data_available=0;
257 }
258 }
259 else
260 {
261 if (filethere(get_data_base_dir("fcc/appl.dat")))
262 {
263 /*fprintf(stderr,"NO NEW FCC, BUT OLD FORMAT FCC DATA AVAILABLE\n");*/
264 if (build_fcc_index(1))
265 {
266 fcc_data_available=1;
267 }
268 else
269 {
270 fprintf(stderr,"Check:Could not build fcc data base index\n");
271 fcc_data_available=0;
272 }
273 }
274 }
275 }
276 return(fcc_data_available);
277 }
278
279
280
281
282
search_fcc_data_appl(char * callsign,FccAppl * data)283 int search_fcc_data_appl(char *callsign, FccAppl *data)
284 {
285 FILE *f;
286 char line[200];
287 int line_pos;
288 char data_in[16385];
289 int found, xx, bytes_read;
290 char temp[15];
291 int len;
292 int which;
293 int i,ii;
294 int pos_it;
295 int llen;
296 char calltemp[8];
297 int pos,ix,num;
298 FILE *fndx;
299 long call_offset = 0;
300 char char_offset[16];
301 char index[32];
302 char appl_file_path[MAX_VALUE];
303
304 data->id_file_num[0] = '\0';
305 data->type_purpose[0] = '\0';
306 data->type_applicant=' ';
307 data->name_licensee[0] = '\0';
308 data->text_street[0] = '\0';
309 data->text_pobox[0] = '\0';
310 data->city[0] = '\0';
311 data->state[0] = '\0';
312 data->zipcode[0] = '\0';
313 data->date_issue[0] = '\0';
314 data->date_expire[0] = '\0';
315 data->date_last_change[0] = '\0';
316 data->id_examiner[0] = '\0';
317 data->renewal_notice=' ';
318 xastir_snprintf(temp,
319 sizeof(temp),
320 "%s",
321 callsign);
322 (void)call_only(temp);
323
324 xastir_snprintf(calltemp, sizeof(calltemp), "%-6.6s", temp);
325 // calltemp doesn't appear to get used anywhere...
326
327 /* add end of field data */
328 strncat(temp, "|", sizeof(temp) - 1 - strlen(temp));
329 len=(int)strlen(temp);
330 found=0;
331 line_pos=0;
332 /* check the database again */
333 which = check_fcc_data();
334
335 // Check for first letter of a U.S. callsign
336 if (! (callsign[0] == 'A' || callsign[0] == 'K' || callsign[0] == 'N' || callsign[0] == 'W') )
337 {
338 return(0); // Not found
339 }
340
341 // ====================================================================
342 // Search thru the index, get the RBA
343 //
344 // This gives us a jumping-off point to start looking in the right
345 // neighborhood for the callsign of interest.
346 //
347 get_user_base_dir("data/appl.ndx", appl_file_path, sizeof(appl_file_path));
348 fndx=fopen(appl_file_path,"r");
349 if (fndx!=NULL)
350 {
351 if (fgets(index,(int)sizeof(index),fndx) == NULL)
352 {
353 // Error occurred
354 fprintf(stderr,"Search:Could not read FCC database index(1): %s\n",appl_file_path);
355 return(0);
356 }
357
358 memcpy(char_offset, &index[6], sizeof(char_offset));
359 char_offset[sizeof(char_offset)-1] = '\0'; // Terminate string
360
361 // Search through the indexes looking for a callsign which is
362 // close to the callsign of interest. If callsign is later in
363 // the alphabet than the current index, snag the next index.
364 while (!feof(fndx) && strncmp(callsign,index,6) > 0)
365 {
366 memcpy(char_offset, &index[6], sizeof(char_offset));
367 char_offset[sizeof(char_offset)-1] = '\0'; // Terminate string
368 if (fgets(index,(int)sizeof(index),fndx) == NULL)
369 {
370 // Error occurred
371 fprintf(stderr,"Search:Could not read FCC database index(2): %s\n", appl_file_path );
372 return(0);
373 }
374 }
375 }
376 else
377 {
378 fprintf(stderr,"Search:Could not open FCC data base index: %s\n", appl_file_path );
379 return (0);
380 }
381 call_offset = atol(char_offset);
382
383 (void)fclose(fndx);
384
385 /* ==================================================================== */
386 /* Continue with the original search */
387 /* */
388
389 f=NULL;
390 switch (which)
391 {
392 case(1):
393 f=fopen(get_data_base_dir("fcc/appl.dat"),"r");
394 break;
395
396 case(2):
397 f=fopen(get_data_base_dir("fcc/EN.dat"),"r");
398 break;
399
400 default:
401 break;
402 }
403 if (f!=NULL)
404 {
405 (void)fseek(f, call_offset,SEEK_SET);
406 while (!feof(f) && !found)
407 {
408 bytes_read=(int)fread(data_in,1,16384,f);
409 if (bytes_read>0)
410 {
411 for (xx=0; (xx<bytes_read) && !found; xx++)
412 {
413 if(data_in[xx]!='\n' && data_in[xx]!='\r')
414 {
415 if (line_pos<199)
416 {
417 line[line_pos++]=data_in[xx];
418 line[line_pos]='\0';
419 }
420 }
421 else
422 {
423 line_pos=0;
424 /*fprintf(stderr,"line:%s\n",line);*/
425 pos=0;
426 num=0;
427 if (which==2)
428 {
429 for (ix=0; ix<14 && !pos; ix++)
430 {
431 if (line[ix]=='|')
432 {
433 num++;
434 if (num==4)
435 {
436 pos=ix+1;
437 }
438 }
439 }
440 }
441 if (strncmp(line+pos,temp,(size_t)len)==0)
442 {
443 found=1;
444 /*fprintf(stderr,"line:%s\n",line);*/
445 llen=(int)strlen(line);
446 /* replace "|" with 0 */
447 for (ii=pos; ii<llen; ii++)
448 {
449 if (line[ii]=='|')
450 {
451 line[ii]='\0';
452 }
453 }
454 pos_it=pos;
455 for (i=0; i<15; i++)
456 {
457 for (ii=pos_it; ii<llen; ii++)
458 {
459 if (line[ii]=='\0')
460 {
461 pos_it=ii;
462 ii=llen+1;
463 }
464 }
465 pos_it++;
466 if (line[pos_it]!='\0')
467 {
468 /*fprintf(stderr,"DATA %d %d:%s\n",i,pos_it,line+pos_it);*/
469 switch (which)
470 {
471 case(1):
472 switch(i)
473 {
474 case(0):
475 xastir_snprintf(data->id_file_num,sizeof(data->id_file_num),"%s",line+pos_it);
476 break;
477
478 case(1):
479 xastir_snprintf(data->type_purpose,sizeof(data->type_purpose),"%s",line+pos_it);
480 break;
481
482 case(2):
483 data->type_applicant=line[pos_it];
484 break;
485
486 case(3):
487 xastir_snprintf(data->name_licensee,sizeof(data->name_licensee),"%s",line+pos_it);
488 break;
489
490 case(4):
491 xastir_snprintf(data->text_street,sizeof(data->text_street),"%s",line+pos_it);
492 break;
493
494 case(5):
495 xastir_snprintf(data->text_pobox,sizeof(data->text_pobox),"%s",line+pos_it);
496 break;
497
498 case(6):
499 xastir_snprintf(data->city,sizeof(data->city),"%s",line+pos_it);
500 break;
501
502 case(7):
503 xastir_snprintf(data->state,sizeof(data->state),"%s",line+pos_it);
504 break;
505
506 case(8):
507 xastir_snprintf(data->zipcode,sizeof(data->zipcode),"%s",line+pos_it);
508 break;
509
510 case(9):
511 xastir_snprintf(data->date_issue,sizeof(data->date_issue),"%s",line+pos_it);
512 break;
513
514 case(11):
515 xastir_snprintf(data->date_expire,sizeof(data->date_expire),"%s",line+pos_it);
516 break;
517
518 case(12):
519 xastir_snprintf(data->date_last_change,sizeof(data->date_last_change),"%s",line+pos_it);
520 break;
521
522 case(13):
523 xastir_snprintf(data->id_examiner,sizeof(data->id_examiner),"%s",line+pos_it);
524 break;
525
526 case(14):
527 data->renewal_notice=line[pos_it];
528 break;
529
530 default:
531 break;
532 }
533 break;
534
535 case(2):
536 switch (i)
537 {
538 case(0):
539 xastir_snprintf(data->id_file_num,sizeof(data->id_file_num),"%s",line+pos_it);
540 break;
541
542 case(2):
543 xastir_snprintf(data->name_licensee,sizeof(data->name_licensee),"%s",line+pos_it);
544 break;
545
546 case(10):
547 xastir_snprintf(data->text_street,sizeof(data->text_street),"%s",line+pos_it);
548 break;
549
550 case(11):
551 xastir_snprintf(data->city,sizeof(data->city),"%s",line+pos_it);
552 break;
553
554 case(12):
555 xastir_snprintf(data->state,sizeof(data->state),"%s",line+pos_it);
556 break;
557
558 case(13):
559 xastir_snprintf(data->zipcode,sizeof(data->zipcode),"%s",line+pos_it);
560 break;
561
562 default:
563 break;
564 }
565 break;
566
567 default:
568 break;
569 }
570 }
571 }
572 }
573 else
574 {
575 // Check whether we passed the alphabetic
576 // location for the callsign. Return if so.
577 if ( (temp[0] < line[pos]) ||
578 ( (temp[0] == line[pos]) && (temp[1] < line[pos+1]) ) )
579 {
580
581 // "Callsign Search", "Callsign Not Found!"
582 popup_message_always(langcode("STIFCC0101"),
583 langcode("STIFCC0102") );
584
585 //fprintf(stderr,"%c%c\t%c%c\n",temp[0],temp[1],line[pos],line[pos+1]);
586 (void)fclose(f);
587 return(0);
588 }
589 }
590 }
591 }
592 }
593 }
594 (void)fclose(f);
595 }
596 else
597 {
598 fprintf(stderr,"Could not open FCC appl data base at: %s\n", get_data_base_dir("fcc/") );
599 }
600 return(found);
601 }
602
603
604