1 // ----------------------------------------------------------------------------
2 // qrzlib.cc
3 //
4 // Interface library to the QRZ database distributed by AA7BQ
5 //
6 // Copyright (C) 1999-2009 David Freese
7 //
8 // This file is part of fldigi.
9 //
10 // Fldigi is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Fldigi is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with fldigi.  If not, see <http://www.gnu.org/licenses/>.
22 // ----------------------------------------------------------------------------
23 
24 #include <config.h>
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <string>
33 
34 #include <iostream>
35 //using namespace std;
36 
37 #include "qrzlib.h"
38 #include "configuration.h"
39 #include "debug.h"
40 
41 static char QRZdir[256] = "";
42 
43 static const char *QRZpath;
44 static const char *QRZtry[] = {
45 #ifdef __WOE32__
46 	"C:/CALLBK/", // look on C: drive first
47 	"D:/CALLBK/",
48 	"E:/CALLBK/",
49 	"F:/CALLBK/",
50 	"G:/CALLBK/",
51 #else
52 	"~/callbk/",
53 	"/cdrom/callbk/",
54 	"/mnt/cdrom/callbk/",  "/mnt/cdrom0/callbk/",  "/mnt/cdrom1/callbk/",
55 	"/media/cdrom/callbk/", "/media/cdrom0/callbk/", "/media/cdrom1/callbk/",
56 #endif
57 	0 };
58 
59 FILE *imagefile = NULL;
60 
61 #define isdirsep(c) ((c)=='/')
62 
filename_expand(char * to,int tolen,const char * from)63 int filename_expand(char *to,int tolen, const char *from) {
64 
65 	char temp[tolen];
66 	strlcpy(temp,from, tolen);
67 	char *start = temp;
68 	char *end = temp+strlen(temp);
69 
70 	int ret = 0;
71 
72   for (char *a=temp; a<end; ) {	// for each slash component
73 	char *e; for (e=a; e<end && !isdirsep(*e); e++); // find next slash
74 	const char *value = 0; // this will point at substitute value
75 	switch (*a) {
76 	case '~':	// a home directory name
77 	  if (e <= a+1) {	// current user's directory
78 	value = getenv("HOME");
79 	  }
80 	  break;
81 	case '$':		/* an environment variable */
82 	  {char t = *e; *(char *)e = 0; value = getenv(a+1); *(char *)e = t;}
83 	  break;
84 	}
85 	if (value) {
86 	  // substitutions that start with slash delete everything before them:
87 	  if (isdirsep(value[0])) start = a;
88 	  int t = strlen(value); if (isdirsep(value[t-1])) t--;
89 	  if ((end+1-e+t) >= tolen) end += tolen - (end+1-e+t);
90 	  memmove(a+t, e, end+1-e);
91 	  end = a+t+(end-e);
92 	  *end = '\0';
93 	  memcpy(a, value, t);
94 	  ret++;
95 	} else {
96 	  a = e+1;
97 	}
98   }
99 
100   strlcpy(to, start, tolen);
101 
102   return ret;
103 }
104 
105 
QRZImageFilename(char * call)106 char *QRZImageFilename (char *call)
107 {
108 	static char fname[80], *p, imgcall[12];
109 	FILE *f;
110 	strcpy(imgcall, call);
111 	p = imgcall;
112 	while (*p) {*p = tolower (*p); p++; }
113 	strcpy (fname, QRZdir);
114 	strcat (fname, "images/");
115 	strcat (fname, &imgcall[strlen(imgcall)-1]);
116 	strcat (fname, "/");
117 	strcat (fname, imgcall);
118 	while (fname[strlen(fname)-1] == ' ') fname[strlen(fname)-1] = 0;
119 	strcat (fname, ".jpg");
120 	f = fl_fopen(fname, "r");
121 	if (f != NULL) {
122 		fclose (f);
123 		return fname;
124 	}
125 	return NULL;
126 }
127 
checkPath(const char * filename)128 int  checkPath( const char *filename )
129 {
130 	char fname[120];
131 	FILE *f;
132 	bool notfound = false;
133 	if (!progdefaults.QRZpathname.empty()) {
134 		strcpy ( fname, progdefaults.QRZpathname.c_str());
135 		for (size_t i = 0; i < strlen(fname); i++)
136 			if (fname[i] == '\\') fname[i] = '/'; // fix for DOS path convention
137 
138 		strcat( fname, filename );
139 		strcat( fname, ".dat" );
140 		if (fname[0] == '~' || fname[0] == '$') {
141 			char f2name[80];
142 			filename_expand(f2name, 79, fname);
143 			strcpy (fname, f2name);
144 		}
145 		f = fl_fopen(fname, "r" );
146 		if( f != NULL )  {
147 			fclose( f );
148 			char pathname[120];
149 			strcpy( pathname, progdefaults.QRZpathname.c_str());
150 			if (pathname[0] == '~' || pathname[0] == '$')
151 				filename_expand(QRZdir, 79, pathname);
152 			else
153 				strcpy (QRZdir, pathname);
154 			return 1;
155 		}
156 		std::string err = fname;
157 		err.append(" not found, performing search");
158 		LOG_WARN("%s", err.c_str());
159 		notfound = true;
160 	}
161 // not specified, perform a search
162 	const char **pQRZpath = QRZtry;
163 	while (*pQRZpath) {
164 		strcpy( fname, *pQRZpath );
165 		strcat( fname, filename );
166 		strcat( fname, ".dat" );
167 		if (fname[0] == '~' || fname[0] == '$') {
168 			char f2name[80];
169 			filename_expand(f2name, 79, fname);
170 			strcpy (fname, f2name);
171 		}
172 		f = fl_fopen(fname, "r" );
173 		if( f != NULL )  {
174 			fclose( f );
175 			QRZpath = *pQRZpath;
176 			if (QRZpath[0] == '~' || QRZpath[0] == '$')
177 				filename_expand(QRZdir, 79, QRZpath);
178 			else
179 				strcpy (QRZdir, QRZpath);
180 			if (notfound) {
181 				std::string err = "Using ";
182 				err.append(fname);
183 				LOG_WARN("%s", err.c_str());
184 			}
185 			return 1;
186 		}
187 		pQRZpath++;
188 	}
189 	QRZpath = QRZtry[0];
190 	LOG_WARN("QRZ data base not found");
191 	return 0;
192 }
193 
SetQRZdirectory(char * dir)194 void SetQRZdirectory(char *dir)
195 {
196 	strcpy(QRZdir, dir);
197 	strcat(QRZdir, "/");
198 }
199 
ImageExists()200 bool QRZ::ImageExists() {
201 	if (Qimagefname == NULL)
202 		return (hasImage = false);
203 	imagefile = fl_fopen(Qimagefname, "r");
204 	if (imagefile) {
205 		fclose (imagefile);
206 		return (hasImage = true);
207 	}
208 	return (hasImage = false);
209 }
210 
OpenQRZFiles(const char * fname)211 void QRZ::OpenQRZFiles( const char *fname )
212 {
213 	long fsize;
214 	char dfname[64];
215 	char idxname[64];
216 	int num1;
217 	int num2;
218 	num1 = 0;
219 	num2 = 0;
220 
221 	if( fname[0] == 0 ) {
222 		QRZvalid = 0;
223 		return;
224 	}
225 
226 	QRZvalid = 1;
227 
228 	if (*QRZdir == 0)
229 		if( checkPath( fname ) == 0 ) {
230 		QRZvalid = 0;
231 		return;
232 		}
233 
234 	strcpy( dfname, QRZdir );
235 	strcpy( idxname, QRZdir );
236 
237 	strcat( idxname, fname );
238 	strcat( idxname, ".idx" );
239 	strcat( dfname, fname );
240 	strcat( dfname, ".dat" );
241 
242 	idxfile = fl_fopen( idxname, "r" );
243 	if( idxfile == NULL ) {
244 		QRZvalid = 0;
245 		return;
246 	}
247 
248 	fseek( idxfile, 0, SEEK_END );
249 	fsize = ftell( idxfile );
250 	rewind( idxfile );
251 
252 	idxsize = fsize - 48;
253 
254 	index = new char[idxsize];
255 
256 	if( index == NULL ) {
257 		fclose( idxfile );
258 		QRZvalid = 0;
259 		return;
260 	}
261 	memset( index, 0, idxsize );
262 
263 	num1 =  fread( &idxhdr.dataname, 48, 1, idxfile );
264 	num2 =  fread( index, idxsize, 1, idxfile );
265 
266 	if (num1 != 1 || num2 != 1) {
267 		fclose( idxfile );
268 		delete [] index;
269 		QRZvalid = 0;
270 		return;
271 	}
272 
273 	fflush( stdout );
274 
275 	fclose( idxfile );
276 
277 	datafile = fl_fopen( dfname, "r" );
278 	if( datafile == NULL ) {
279 		delete [] index;
280 		QRZvalid = 0;
281 		return;
282 	}
283 
284 	sscanf( idxhdr.bytesperkey, "%d", &datarecsize );
285 	if( datarecsize == 0 || datarecsize > 32767 ) {
286 		delete [] index;
287 		QRZvalid = 0;
288 		return;
289 	}
290 
291 // allocate sufficient data buffer for file read over key boundary
292 
293 	if (data) delete [] data;
294 	data = new char[datarecsize + 512];
295 
296 	if( data == NULL ) {
297 		delete [] index;
298 		QRZvalid = 0;
299 		return;
300 	}
301 // fill buffer with new-lines to insure not reading past end of
302 // the buffer
303 	memset( data, '\n', datarecsize + 512 );
304 
305 	sscanf( idxhdr.keylen, "%d", &keylen );
306 	sscanf( idxhdr.numkeys, "%ld", &numkeys );
307 	top = index + idxsize - keylen;
308 
309 }
310 
311 
QRZ(const char * fname)312 QRZ::QRZ( const char *fname )
313 {
314 	int len = strlen(fname);
315 	criteria = fname[ len - 1 ];
316 	OpenQRZFiles( fname );
317 }
318 
QRZ(const char * fname,char c)319 QRZ::QRZ( const char *fname, char c )
320 {
321 	criteria = c;
322 	OpenQRZFiles( fname );
323 }
324 
NewDBpath(const char * fname)325 void QRZ::NewDBpath( const char *fname )
326 {
327 	int len = strlen(fname);
328 	criteria = fname[ len - 1 ];
329 	*QRZdir = 0;
330 	OpenQRZFiles( fname );
331 }
332 
333 
~QRZ()334 QRZ::~QRZ()
335 {
336 	if (index) delete [] index;
337 	if (data) delete [] data;
338 	if( datafile != NULL ) fclose( datafile );
339 	return;
340 }
341 
CallComp(char * s1,char * s2)342 int QRZ::CallComp( char *s1, char *s2 )
343 {
344 	static char sa[7], sb[7];
345 	strncpy( sb, s2, 6 );
346 	strncpy( sa, s1, 6 );
347 	sa[6] = 0;
348 	sb[6] = 0;
349 
350 	int stest = strncasecmp( sa + 3, sb + 3, 3 );
351 	if( stest < 0 )
352 		return -1;
353 	if( stest > 0 )
354 		return 1;
355 // suffix are equal
356 	int atest = strncasecmp( sa + 2, sb + 2, 1 );
357 	if( atest < 0 )
358 		return -1;
359 	if( atest > 0 )
360 		return 1;
361 // suffix & call area are equal
362 	int ptest = strncasecmp( sa, sb, 2 );
363 	if( ptest < 0 )
364 		return -1;
365 	if( ptest > 0 )
366 		return 1;
367 // total match of calls
368 	return 0;
369 }
370 
Composite(char * s)371 char *Composite( char *s )
372 {
373 	static char newstr[7];
374 	int ccount = strlen(s) < 7 ? strlen(s) : 6;
375 	memset(newstr, ' ', 6 );
376 	newstr[6] = 0;
377 	if( isdigit( s[2] ) ) {
378 		for( int i = 0; i < ccount; i++ )
379 			newstr[i] = s[i];
380 	} else {
381 		newstr[0] = s[0];
382 		newstr[2] = s[1];
383 		for( int i = 2; i < ccount; i++ )
384 			newstr[i+1] = s[i];
385 	}
386 	return( newstr );
387 }
388 
ReadDataBlock(long p)389 int QRZ::ReadDataBlock( long p )
390 {
391 	rewind( datafile );
392 
393 	if ( p < 0 ) p = 0;
394 
395 	if( fseek( datafile, p, SEEK_SET ) != 0 ) {
396 		return 1;
397 	}
398 
399 	databytesread = fread( data, 1, datarecsize + 512, datafile );
400 	dataoffset = p;
401 
402 	fflush( stdout);
403 	return 0;
404 }
405 
FindCallsign(char * field)406 int QRZ::FindCallsign( char *field )
407 {
408 	char composite[7], testcall[7];
409 	char *endofdata;
410 	int  matched = 0, iOffset;
411 
412 	memset( composite, 0, 6 );
413 	memset( testcall, 0, 6 );
414 	found = 0;
415 	idxptr = index;
416 
417 	if( strlen( field ) < 3 )  // must be a valid callsign
418 		return 0;
419 
420 	if ( !(isdigit( field[1] ) || isdigit( field[2] ) ) )
421 		return 0;
422 
423 	strcpy( composite, Composite( field ) );
424 
425 	for( iOffset = 0; iOffset < numkeys; iOffset++, idxptr += keylen )
426 		if( CallComp( composite, idxptr) <= 0 )
427 			break;
428 
429 	iOffset--;
430 	if (iOffset < 0) iOffset = 0;
431 
432 	ReadDataBlock( datarecsize * iOffset );
433 
434 	dfptr = data;
435 	endofdata = data + databytesread;
436 
437 	endofline = strchr( dfptr, '\n' );
438 
439 	if( idxptr != index ) {
440 		endofline = strchr( dfptr, '\n' );
441 		if (endofline != NULL )
442 			dfptr = endofline + 1;
443 	}
444 
445 	found = 0;
446 
447 	while ( !found && (dfptr < endofdata ) ) {
448 		memcpy( testcall, dfptr, 6 );
449 		if( (matched = CallComp( composite, Composite(testcall) ) ) <= 0 )
450 			found = 1;
451 		else {
452 			endofline = strchr( dfptr, '\n' );
453 			dfptr = endofline + 1;
454 		}
455 	}
456 
457 	if ( matched == 0 ) {
458 		endofline = strchr( dfptr, '\n' );
459 		*endofline = 0;
460 		strcpy( recbuffer, dfptr );
461 // check for old call referencing new call
462 		if (strlen(recbuffer) < 15 ) {
463 			dfptr = strchr( dfptr, ',' ) + 1;
464 			strcpy( recbuffer, dfptr );
465 //	  Qcall = recbuffer;
466 			found = -1;
467 		} else {
468 			found = 1;
469 			dfptr = endofline + 1;  // point to next record
470 		}
471 		return (found);
472 	}
473 	found = 0;
474 	return 0;
475 }
476 
nextrec()477 int QRZ::nextrec()
478 {
479 	if( dfptr > data + datarecsize ) {
480 		if( ReadDataBlock( dataoffset + (dfptr - data) ) != 0)
481 			return 0;
482 		dfptr = data;
483 	}
484 
485 	endofline = strchr( dfptr, '\n' );
486 	*endofline = 0;
487 	strcpy( recbuffer, dfptr );
488 	dfptr = endofline + 1;
489 	if (strlen(recbuffer) < 15 ) {
490 		nextrec();
491 	}
492 	return 1;
493 }
494 
NextRecord()495 int QRZ::NextRecord()
496 {
497 	if( nextrec() == 1 )
498 		return( ReadRec() );
499 	return 0;
500 }
501 
FindName(char * field)502 int QRZ::FindName( char *field )
503 {
504 	char *endofdata;
505 	int  matched = 0, iOffset;
506 	char *Lname, *Fname;
507 	char sFname[17];
508 	char sLname[17];
509 	char sIdxName[33];
510 	char *cptr;
511 
512 	memset( sFname, 0, 17 );
513 	memset( sLname, 0, 17 );
514 	memset( sIdxName, 0, 33 );
515 
516 	if ( (cptr = strchr( field, ',' ) ) != NULL ) {
517 		strncpy( sLname, field, cptr - field );
518 		strcpy( sFname, cptr + 1 );
519 	} else
520 		strcpy( sLname, field );
521 
522 	strcpy( sIdxName, sLname );
523 	if( strlen( sFname ) > 0 ) {
524 		strcat( sIdxName, " " );
525 		strcat( sIdxName, sFname );
526 	}
527 
528 	found = 0;
529 	idxptr = index;
530 
531 	for( iOffset = 0; iOffset < numkeys; iOffset++, idxptr += keylen )
532 		if( strncasecmp( sIdxName, idxptr, keylen ) <= 0 )
533 			break;
534 
535 	iOffset--;
536 	if (iOffset < 0) iOffset = 0;
537 
538 	ReadDataBlock( datarecsize * iOffset );
539 
540 	dfptr = data;
541 	endofdata = data + databytesread;
542 
543 	if( idxptr != index ) {
544 		endofline = strchr( dfptr, '\n' );
545 		if (endofline != NULL )
546 			dfptr = endofline + 1;
547 	}
548 
549 	found = 0;
550 	while ( !found && (dfptr < endofdata ) ) {
551 		endofline = strchr( dfptr, '\n' );
552 		if( endofline == NULL || endofline > endofdata )
553 			break;
554 		if( endofline - dfptr > 14 ) {			// valid racord
555 			Lname = strchr( dfptr, ',' ) + 1;	   // locate Lname element
556 			Fname = strchr( Lname, ',' ) + 1;	   // locate Fname element
557 			if( *Fname == ',' )
558 				Fname++;
559 			else
560 				Fname = strchr( Fname, ',' ) + 1;
561 			if( (matched = strncasecmp( sLname, Lname, strlen(sLname) ) ) == 0 ) {
562 				if( sFname[0] == 0 )
563 					found = 1;
564 			else
565 				if( ( matched = strncasecmp( sFname, Fname, strlen(sFname) ) ) <= 0 )
566 					found = 1;
567 			}
568 		}
569 	if (!found && (dfptr < endofdata ) )
570 		dfptr = strchr( dfptr, '\n' ) + 1;	// move to next record
571 	}
572 
573 	if ( matched == 0 ) {
574 		endofline = strchr( dfptr, '\n' );
575 		*endofline = 0;
576 		strcpy( recbuffer, dfptr );
577 		found = 1;
578 		dfptr = endofline + 1;  // point to next record
579 		return (found);
580 	}
581 	found = 0;
582 	return 0;
583 }
584 
CompState(const char * field,const char * state,const char * city)585 int QRZ::CompState( const char *field, const char *state, const char *city )
586 {
587 	int compsize = strlen(field+2),
588 		chk;
589 	if (compsize > keylen) compsize = keylen;
590 
591 	if(strlen( field ) == 2)
592 		return ( strncasecmp( field, state, 2 ) );
593 
594 	if( (chk = strncasecmp( field, state, 2 ) ) < 0 )
595 		return -1;
596 	if( chk > 0 )
597 		return 1;
598 	chk = strncasecmp( field + 2, city, compsize);
599 	if (chk < 0)
600 		return -1;
601 	if (chk > 0)
602 		return 1;
603 	return 0;
604 }
605 
FindState(char * field)606 int QRZ::FindState( char *field )
607 {
608 	char *endofdata;
609 	int  matched = 0, iOffset;
610 	char *state;
611 	char *city;
612 	int  compsize = strlen(field);
613 
614 	if (compsize > keylen) compsize = keylen;
615 
616 	found = 0;
617 	idxptr = index;
618 
619 	for( iOffset = 0; iOffset < numkeys; iOffset++, idxptr += keylen )
620 		if( strncasecmp( field, idxptr, compsize ) <= 0 )
621 			break;
622 
623 	iOffset--;
624 	if (iOffset < 0) iOffset = 0;
625 
626 	ReadDataBlock( datarecsize * iOffset );
627 
628 	dfptr = data;
629 	endofdata = data + datarecsize;
630 
631 	if( idxptr != index ) {
632 		endofline = strchr( dfptr, '\n' );
633 		if (endofline != NULL )
634 		dfptr = endofline + 1;
635 	}
636 
637 	found = 0;
638 	while ( !found && (dfptr < endofdata ) ) {
639 		endofline = strchr( dfptr, '\n' );
640 		if( endofline - dfptr > 14 ) {			// valid record
641 
642 			city = dfptr;
643 			for( int i = 0; i < 9; i++ )			 // move to city element
644 				city = strchr( city, ',' ) + 1;
645 			state = strchr( city, ',' ) + 1;		 // move to state element
646 			matched = CompState( field, state, city );
647 
648 			if( matched == 0)
649 				found = 1;
650 			else {
651 				endofline = strchr( dfptr, '\n' );  // no match, move to next
652 				dfptr = endofline + 1;
653 			}
654 		} else {
655 			endofline = strchr( dfptr, '\n' );	// invalid record, move to next
656 			dfptr = endofline + 1;
657 		}
658 	}
659 
660 	if ( matched == 0 ) {
661 		endofline = strchr( dfptr, '\n' );
662 		*endofline = 0;
663 		strcpy( recbuffer, dfptr );
664 		found = 1;
665 		dfptr = endofline + 1;  // point to next record
666 		return (found);
667 	}
668 	found = 0;
669 	return 0;
670 }
671 
FindZip(char * field)672 int QRZ::FindZip( char *field )
673 {
674 	char *endofdata;
675 	int  matched = 0, iOffset;
676 	char *zip;
677 
678 	found = 0;
679 	idxptr = index;
680 
681 	for( iOffset = 0; iOffset < numkeys; iOffset++, idxptr += keylen )
682 		if( strncasecmp( field, idxptr, 5 ) <= 0 )
683 		break;
684 
685 	iOffset--;
686 	if (iOffset < 0) iOffset = 0;
687 
688 	ReadDataBlock( datarecsize * iOffset );
689 
690 	dfptr = data;
691 	endofdata = data + datarecsize;
692 
693 	if( idxptr != index ) {
694 		endofline = strchr( dfptr, '\n' );
695 		if (endofline != NULL )
696 			dfptr = endofline + 1;
697 	}
698 
699 	found = 0;
700 	while ( !found && (dfptr < endofdata ) ) {
701 		endofline = strchr( dfptr, '\n' );
702 
703 		if( endofline - dfptr > 14 ) {			// valid record
704 			zip = dfptr;
705 			for( int i = 0; i < 11; i++ )			 // move to Zip element
706 				zip = strchr( zip, ',' ) + 1;
707 			if( (matched = strncasecmp( field, zip, 5 ) ) <= 0 )
708 				found = 1;
709 			else {
710 				endofline = strchr( dfptr, '\n' );  // no match, move to next
711 				dfptr = endofline + 1;
712 			}
713 		} else {
714 			endofline = strchr( dfptr, '\n' );	// invalid record, move to next
715 			dfptr = endofline + 1;
716 		}
717 	}
718 
719 	if ( matched == 0 ) {
720 		endofline = strchr( dfptr, '\n' );
721 		*endofline = 0;
722 		strcpy( recbuffer, dfptr );
723 		found = 1;
724 		dfptr = endofline + 1;  // point to next record
725 		return (found);
726 	}
727 	found = 0;
728 	return 0;
729 }
730 
FindRecord(char * field)731 int QRZ::FindRecord( char *field )
732 {
733 	if (QRZvalid == 0 ) return 0;
734 
735 	switch (criteria) {
736 		case 'c' :
737 			FindCallsign( field );
738 			break;
739 		case 'n' :
740 			FindName( field );
741 			break;
742 		case 's' :
743 			FindState( field );
744 			break;
745 		case 'z' :
746 			FindZip( field );
747 	}
748 	return( ReadRec() );
749 }
750 
751 
752 
ReadRec()753 int QRZ::ReadRec()
754 {
755 	char *comma;
756 	static char empty[] = { '\0' };
757 
758 	if( found == 1 ) {
759 		Qcall = recbuffer;
760 		comma = strchr( Qcall, ',' );
761 		*comma = 0;
762 		Qlname = comma + 1;
763 		comma = strchr( Qlname, ',' );
764 		*comma = 0;
765 		Qfname = comma + 1;
766 		comma = strchr( Qfname, ',' );
767 		Qfname = comma + 1;	  // skip JR field
768 		comma = strchr( Qfname, ',' );
769 		*comma = 0;
770 		Qdob = comma + 1;
771 		comma = strchr( Qdob, ',' );
772 		Qdob = comma + 1;		// skip MI field
773 		comma = strchr( Qdob, ',' );
774 		*comma = 0;
775 		Qefdate = comma + 1;
776 		comma = strchr( Qefdate, ',' );
777 		*comma = 0;
778 		Qexpdate = comma + 1;
779 		comma = strchr( Qexpdate, ',' );
780 		*comma = 0;
781 		Qmail_str = comma + 1;
782 		comma = strchr( Qmail_str, ',' );
783 		*comma = 0;
784 		Qmail_city = comma + 1;
785 		comma = strchr( Qmail_city, ',' );
786 		*comma = 0;
787 		Qmail_st = comma + 1;
788 		comma = strchr( Qmail_st, ',' );
789 		*comma = 0;
790 		Qmail_zip = comma + 1;
791 		comma = strchr( Qmail_zip, ',' );
792 		*comma = 0;
793 		Qopclass = comma + 1;
794 		comma = strchr( Qopclass, ',' );
795 		*comma = 0;
796 		Qp_call = comma + 1;
797 		comma = strchr( Qp_call, ',' );
798 		*comma = 0;
799 		Qp_class = comma + 1;
800 		//Qp_class[1] = 0;
801 		*(comma + 2) = 0;
802 		Qimagefname = QRZImageFilename (GetCall());
803 		return( 1 );
804 	} else {
805 		Qcall = empty;
806 		Qlname = empty;
807 		Qfname = empty;
808 		Qdob = empty;
809 		Qefdate = empty;
810 		Qexpdate = empty;
811 		Qmail_str = empty;
812 		Qmail_city = empty;
813 		Qmail_st = empty;
814 		Qmail_zip = empty;
815 		Qopclass = empty;
816 		Qp_call = empty;
817 		Qp_class = empty;
818 		Qimagefname = NULL;
819 		return( 0 );
820 	}
821 }
822 
GetCount(char * unknown)823 int QRZ::GetCount( char *unknown )
824 {
825 	int matched, cnt = 0;
826 	char temp[40];
827 
828 	if( FindRecord( unknown ) != 1 )
829 		return(0);
830 	matched = 0;
831 	while (matched == 0) {
832 		cnt++;
833 		NextRecord();
834 		switch (criteria) {
835 			case 'c' :
836 				matched = 1;
837 				break;
838 			case 'n' :
839 				if( strchr( unknown, ',' ) == 0 )
840 					matched = strcasecmp( unknown, GetLname() );
841 				else {
842 					strcpy( temp, GetLname() );
843 					strcat( temp, "," );
844 					strcat( temp, GetFname() );
845 					matched = strncasecmp( unknown, temp, strlen(unknown) );
846 				}
847 				break;
848 			case 'z' :
849 				matched = strncmp( unknown, GetZIP(), 5 );
850 				break;
851 			case 's' :
852 				matched = CompState( unknown, GetState(), GetCity() );
853 				break;
854 			default  :
855 				matched = 1;
856 		}
857 	}
858 	return cnt;
859 }
860 
GetCall()861 char * QRZ::GetCall()
862 {
863 	static char call[15];
864 	char *p = call;
865 	strcpy (call, Qcall);
866 	while (*p) {
867 		if (*p == ' ') strcpy (p, p+1);
868 		if (*p != ' ') p++;
869 	}
870 	return( call );
871 };
872 
GetLname()873 const char * QRZ::GetLname()
874 {
875 	return( Qlname );
876 };
877 
GetFname()878 const char * QRZ::GetFname()
879 {
880 	return( Qfname );
881 };
882 
GetDOB()883 const char * QRZ::GetDOB()
884 {
885 	return( Qdob );
886 };
887 
GetEFdate()888 const char * QRZ::GetEFdate()
889 {
890 	return( Qefdate );
891 };
892 
GetEXPdate()893 const char * QRZ::GetEXPdate()
894 {
895 	return( Qexpdate );
896 };
897 
GetStreet()898 const char * QRZ::GetStreet()
899 {
900 	return( Qmail_str );
901 };
902 
GetCity()903 const char * QRZ::GetCity()
904 {
905 	return( Qmail_city );
906 };
907 
GetState()908 const char * QRZ::GetState()
909 {
910 	return( Qmail_st );
911 };
912 
GetZIP()913 const char * QRZ::GetZIP()
914 {
915 	return( Qmail_zip );
916 };
917 
GetOPclass()918 const char * QRZ::GetOPclass()
919 {
920 	return( Qopclass );
921 };
922 
GetPriorCall()923 const char * QRZ::GetPriorCall()
924 {
925 	return( Qp_call );
926 };
927 
GetPriorClass()928 const char * QRZ::GetPriorClass()
929 {
930 	return( Qp_class );
931 };
932 
getQRZvalid()933 int QRZ::getQRZvalid()
934 {
935 	return( QRZvalid );
936 }
937 
GetImageFileName()938 const char * QRZ::GetImageFileName ()
939 {
940 	return (Qimagefname);
941 }
942 
CSV_Record()943 char * QRZ::CSV_Record()
944 {
945 	static char info[256];
946 	memset( info, 0, 256 );
947 	snprintf( info,  sizeof(info) - 1, "%s,%s,%s,%s,%s,%s,%s,%s,%s",
948 		GetCall(), Qopclass, Qefdate,
949 		Qlname, Qfname, Qmail_str, Qmail_city, Qmail_st, Qmail_zip );
950 	return info;
951 }
952 
Fmt_Record()953 char *QRZ::Fmt_Record()
954 {
955 	static char info[256];
956 	memset( info, 0, 256 );
957 	snprintf( info, sizeof(info) - 1, "%s   %s : %s\n%s %s\n%s\n%s, %s  %s\n",
958 		GetCall(), Qopclass, Qefdate,
959 		Qfname, Qlname,
960 		Qmail_str,
961 		Qmail_city, Qmail_st, Qmail_zip
962 	);
963 	return info;
964 }
965 
966 
967