1 /*  asndebin.c
2 * ===========================================================================
3 *
4 *                            PUBLIC DOMAIN NOTICE
5 *               National Center for Biotechnology Information
6 *
7 *  This software/database is a "United States Government Work" under the
8 *  terms of the United States Copyright Act.  It was written as part of
9 *  the author's official duties as a United States Government employee and
10 *  thus cannot be copyrighted.  This software/database is freely available
11 *  to the public for use. The National Library of Medicine and the U.S.
12 *  Government have not placed any restriction on its use or reproduction.
13 *
14 *  Although all reasonable efforts have been taken to ensure the accuracy
15 *  and reliability of the software and data, the NLM and the U.S.
16 *  Government do not and cannot warrant the performance or results that
17 *  may be obtained by using this software or data. The NLM and the U.S.
18 *  Government disclaim all warranties, express or implied, including
19 *  warranties of performance, merchantability or fitness for any particular
20 *  purpose.
21 *
22 *  Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * File Name:  asndebin.c
27 *
28 * Author:  James Ostell
29 *
30 * Version Creation Date: 3/4/91
31 *
32 * $Revision: 6.16 $
33 *
34 * File Description:
35 *   Special binary form (BER) decoder for ASN.1
36 *
37 * Modifications:
38 * --------------------------------------------------------------------------
39 * Date     Name        Description of modification
40 * -------  ----------  -----------------------------------------------------
41 *
42 * ==========================================================================
43 */
44 
45 #include "asnbuild.h"
46 
47 #define ASNDEBIN_EOF -2
48 
RelaxVisibleStringUTF8(AsnIoPtr aip,AsnTypePtr atp)49 static void RelaxVisibleStringUTF8 (AsnIoPtr aip, AsnTypePtr atp) {
50 
51   Int2  isa = 0;
52   Uint1 fix_utf8_in;
53 
54   if (aip == NULL || atp == NULL) return;
55   if (atp->type != NULL) {
56     isa = atp->type->isa;
57   } else {
58     isa = atp->isa;
59   }
60   if (! ISA_STRINGTYPE (isa)) return;
61   if (aip->tagclass != atp->tagclass) return;
62   if (aip->tagnumber == atp->tagnumber) return;
63 
64   /* !!! CXX-3341 temporarily allow UTF8/VisibleString flexibility !!! */
65   fix_utf8_in = aip->fix_utf8_in;
66   if (fix_utf8_in == 3) return;
67 
68   if (aip->tagnumber == TAG_VISIBLESTRING && atp->tagnumber == TAG_UTF8STRING) {
69     aip->tagnumber = atp->tagnumber;
70   } else if (aip->tagnumber == TAG_UTF8STRING && atp->tagnumber == TAG_VISIBLESTRING) {
71     aip->tagnumber = atp->tagnumber;
72 
73     if (fix_utf8_in == 0) {
74       aip->utf8_read = TRUE;
75     } else if (fix_utf8_in == 1) {
76       if (! aip->utf8_read) {
77         AsnIoErrorMsg(aip, 107);
78       }
79       aip->utf8_read = TRUE;
80     } else if (fix_utf8_in == 2) {
81       AsnIoErrorMsg(aip, 107);
82       aip->utf8_read = TRUE;
83     }
84   }
85 }
86 
87 /*****************************************************************************
88 *
89 *   AsnTypePtr AsnBinReadId(aip, atp)
90 *   	reads identifier for next value
91 *
92 *****************************************************************************/
AsnBinReadId(AsnIoPtr aip,AsnTypePtr atp)93 NLM_EXTERN AsnTypePtr LIBCALL  AsnBinReadId (AsnIoPtr aip, AsnTypePtr atp)
94 {
95 	Int4 used;
96 
97 	Int2 isa;
98 	AsnTypePtr atp2, atp3, atp4;
99 	Boolean found;
100     PstackPtr psp, prevpsp, currpsp;
101 
102 	used = 0;
103 
104 	if (! aip->type_indent)    /* just starting or ending reading */
105 	{
106 		if (atp == NULL)       /* starting an unknown item */
107 		{
108 			AsnIoErrorMsg(aip, 1);
109 			return NULL;
110 		}
111 
112 		used = AsnDeBinScanTag(aip);   /* read the tag */
113 
114 		if (used == ASNDEBIN_EOF)      /* end of file */
115 			return NULL;
116                 /* see RT toolbox ticket 15030485 for the below fix */
117 
118 		atp2 = AsnFindBaseType(atp);   /* find the base type */
119 		if (atp2 == NULL)
120 			return atp2;
121 		if (atp2->type == NULL)
122 			return atp2->type;
123 		isa = atp2->type->isa;
124 
125 
126 		if (atp2->type->isa != CHOICE_TYPE)
127 		{
128 			atp2 = atp2->type;         /* will be primitive tag */
129 
130             RelaxVisibleStringUTF8 (aip, atp2);
131 
132 			if ((aip->tagclass != atp2->tagclass) ||
133 				(aip->tagnumber != atp2->tagnumber))
134 				found = FALSE;
135 			else
136 				found = TRUE;
137 		}
138 		else
139 		{
140 			atp2 = (AsnTypePtr) atp->branch;      /* look for a match among choices */
141 			found = FALSE;
142 			while ((atp2 != NULL) && (! found))
143 			{
144                 RelaxVisibleStringUTF8 (aip, atp2);
145 
146 				if ((aip->tagclass == atp2->tagclass) &&
147 					(aip->tagnumber == atp2->tagnumber))
148 					found = TRUE;
149 				else
150 					atp2 = atp2->next;
151 			}
152 			aip->tagsaved = TRUE;    /* will need tag for which CHOICE next round */
153 		}
154 
155 		if (! found)
156 		{
157 			AsnIoErrorMsg(aip, 2, AsnErrGetTypeName(atp->name));
158 			return NULL;
159 		}
160 
161         psp = & aip->typestack[0];
162         psp->len = aip->length;
163         psp->type = atp;
164         psp->resolved = FALSE;
165         psp->tag_indef = FALSE;
166 
167 		return atp;
168 	}
169 
170     prevpsp = & aip->typestack[aip->type_indent - 1];   /* previous level */
171     currpsp = prevpsp + 1;                              /* current level */
172 
173 							/** end of definate length struct ****/
174 	if (prevpsp->len == 0)
175 	{
176 		prevpsp->resolved = TRUE;
177 		return prevpsp->type;
178 	}
179 
180 	if (currpsp->type != NULL)  /* reading a struct */
181 	{
182 		if (! aip->tagsaved)       /* already read it? */
183 		{
184 			used = AsnDeBinScanTag(aip);    /* read the tag */
185 			if (! AsnDeBinDecr(used, aip))  /* decrement length counter */
186 				return NULL;
187 		}
188 
189 		if ((aip->length == 0) && (aip->tagclass == 0) &&
190 			(aip->tagnumber == 0))     /* length 0, could be end of contents */
191 		{
192 			if (prevpsp->len == INDEFINATE)
193 			{
194                 prevpsp->resolved = TRUE;
195 				aip->tagsaved = FALSE;
196 				if (prevpsp->tag_indef)      /* indefinate user tag? */
197 				{
198 					used = AsnDeBinScanTag(aip);   /* should be 00 for tag */
199 					if (! AsnDeBinDecr(used, aip))
200 						return NULL;
201 					if ((aip->length == 0) && (aip->tagclass == 0) &&
202 						(aip->tagnumber == 0))
203 						prevpsp->tag_indef = FALSE;
204 					else
205 					{
206 						AsnIoErrorMsg(aip, 3, AsnErrGetTypeName(prevpsp->type->name));
207 						return NULL;
208 					}
209 				}
210 				return prevpsp->type;
211 			}
212 		}
213 		else
214 			aip->tagsaved = TRUE;
215 	}
216 
217 
218 	if (aip->type_indent)     /* check for SEQOF and SETOF */
219 	{
220 		atp = prevpsp->type;
221 		atp2 = AsnFindBaseType(atp);
222 		isa = atp2->type->isa;
223 		if ((isa == SEQOF_TYPE) || (isa == SETOF_TYPE))
224 		{
225 			atp = (AsnTypePtr) atp2->branch;   /* set of what type? */
226 			currpsp->type = atp;
227             currpsp->len = INDEFINATE;
228             currpsp->resolved = FALSE;
229             currpsp->tag_indef = FALSE;
230 			atp2 = AsnFindBaseType(atp);
231 			isa = atp2->type->isa;
232 			atp2 = atp2->type;        /* get universal type */
233 			used = AsnDeBinScanTag(aip);   /* read the tag */
234 			if (! AsnDeBinDecr(used, aip))
235 				return NULL;
236 
237             RelaxVisibleStringUTF8 (aip, atp2);
238 
239 			if ((aip->tagclass != atp2->tagclass) ||
240 				(aip->tagnumber != atp2->tagnumber))
241 			{
242 				if ((aip->length == 0) && (aip->tagclass == 0) &&
243 					(aip->tagnumber == 0))     /* length 0, could be end of contents */
244 				{      /* this handles an empty SEQ OF/SET OF ***/
245 					if (prevpsp->len == INDEFINATE)
246 					{
247             		    prevpsp->resolved = TRUE;
248 						aip->tagsaved = FALSE;
249 						if (prevpsp->tag_indef)      /* indefinate user tag? */
250 						{
251 							used = AsnDeBinScanTag(aip);   /* should be 00 for tag */
252 							if (! AsnDeBinDecr(used, aip))
253 								return NULL;
254 							if ((aip->length == 0) && (aip->tagclass == 0) &&
255 								(aip->tagnumber == 0))
256 								prevpsp->tag_indef = FALSE;
257 							else
258 							{
259 								AsnIoErrorMsg(aip, 3, AsnErrGetTypeName(prevpsp->type->name));
260 								return NULL;
261 							}
262 						}
263 						return prevpsp->type;
264 					}
265 				}
266 				else if (isa == CHOICE_TYPE) /* no tag */
267 				{
268 					aip->tagsaved = TRUE;
269 				}
270 				else
271 				{
272 					AsnIoErrorMsg(aip, 4, AsnErrGetTypeName(atp->name));
273 					return NULL;
274 				}
275 			}
276 			currpsp->len = aip->length;
277 			return atp;   /* no type identifier */
278 		}
279 	}
280 
281 	used = AsnDeBinScanTag(aip);    /* read the tag */
282 	if (! AsnDeBinDecr(used, aip))  /* decrement length counter */
283 		return NULL;
284 
285 	if ((aip->length == 0) && (aip->tagclass == 0) &&
286 		(aip->tagnumber == 0))     /* length 0, could be end of contents */
287 	{
288 		if (prevpsp->len == INDEFINATE)
289 		{
290             prevpsp->resolved = TRUE;
291 			aip->tagsaved = FALSE;
292 			if (prevpsp->tag_indef)      /* indefinate user tag? */
293 			{
294 				used = AsnDeBinScanTag(aip);   /* should be 00 for tag */
295 				if (! AsnDeBinDecr(used, aip))
296 					return NULL;
297 				if ((aip->length == 0) && (aip->tagclass == 0) &&
298 					(aip->tagnumber == 0))
299 					prevpsp->tag_indef = FALSE;
300 				else
301 				{
302 					AsnIoErrorMsg(aip, 3, AsnErrGetTypeName(prevpsp->type->name));
303 					return NULL;
304 				}
305 			}
306 			return prevpsp->type;
307 		}
308 	}
309 
310 	atp2 = AsnFindBaseType(prevpsp->type);
311 	atp = AsnDeBinFindElement(aip, (AsnTypePtr) atp2->branch);
312 	if (atp == NULL)
313 	{
314 		AsnIoErrorMsg(aip, 5, AsnErrGetTypeName(prevpsp->type->name));
315 		return NULL;
316 	}
317 
318 	if (atp2->type->isa == SEQ_TYPE)      /* check sequence order */
319 	{
320 		atp3 = currpsp->type;
321 		if (atp3 != NULL)
322 		{
323 			atp4 = (AsnTypePtr) atp2->branch;
324 			atp3 = atp3->next;
325 			while (atp4 != atp3)
326 			{
327 				if (atp == atp4)
328 				{
329 					AsnIoErrorMsg(aip, 6, AsnErrGetTypeName(atp->name), AsnErrGetTypeName(atp2->name));
330 					return NULL;
331 				}
332 				atp4 = atp4->next;
333 			}
334 		}
335 		else
336 			atp3 = (AsnTypePtr) atp2->branch;
337 
338 		while ((atp3 != NULL) && (atp3 != atp))
339 		{
340 			if (! (atp3->optional || atp3->hasdefault))
341 			{
342 				AsnIoErrorMsg(aip, 7, AsnErrGetTypeName(atp3->name), AsnErrGetTypeName(atp2->name));
343 				return NULL;
344 			}
345 			atp3 = atp3->next;
346 		}
347 	}
348 
349 	currpsp->type = atp;
350 	currpsp->len = aip->length;
351 	currpsp->resolved = FALSE;    /* mark first use */
352 	if ((atp->tagclass != TAG_UNIVERSAL) && (atp->tagclass != TAG_NONE)
353 		&& (aip->length == INDEFINATE))
354 			currpsp->tag_indef = TRUE;
355 	return atp;
356 }
357 
358 /*****************************************************************************
359 *
360 *   Boolean AsnDeBinDecr(used, aip)
361 *   	decrement all levels above level with used bytes
362 *
363 *****************************************************************************/
AsnDeBinDecr(Int4 used,AsnIoPtr aip)364 NLM_EXTERN Boolean AsnDeBinDecr (Int4 used, AsnIoPtr aip)
365 {
366 	PstackPtr	psp, psp0;
367 
368 	if (used == ASNDEBIN_EOF) return FALSE; /* avoid infinite loop in higher levels */
369 
370 	if (used <= 0) /* tag saved or INDEFINATE */
371 		return TRUE;
372 
373 	psp = (psp0 = aip->typestack) + aip->type_indent;
374 	while (psp > psp0) {
375 		--psp;
376 		if (psp->len == INDEFINATE) /* if one INDEFINATE, assume all are */
377 			return TRUE;
378 		if ((psp->len -= used) < 0) {
379 			AsnIoErrorMsg(aip, 8, (int)(psp - psp0) /* level */);
380 			return FALSE;
381 		}
382 	}
383 	return TRUE;
384 }
385 
386 /**** old version ***********************
387 NLM_EXTERN Boolean AsnDeBinDecr (Int4 used, AsnIoPtr aip)
388 {
389 	Int2 level;
390 
391 	if (used == INDEFINATE)
392 		return TRUE;
393 
394 	level = aip->type_indent;
395 	while (level)
396 	{
397 		level--;
398 		if (aip->typestack[level].len != INDEFINATE)
399 		{
400 			aip->typestack[level].len -= used;
401 			if (aip->typestack[level].len < 0)
402 			{
403 				AsnIoErrorMsg(aip, 8, level);
404 				return FALSE;
405 			}
406 		}
407 	}
408 	return TRUE;
409 }
410 *****************************************/
411 /*****************************************************************************
412 *
413 *   Int4 AsnDeBinScanTag(aip)
414 *   	scan the next tag-length element
415 *   	return bytes used from input
416 *
417 *****************************************************************************/
AsnDeBinScanTag(AsnIoPtr aip)418 NLM_EXTERN Int4 AsnDeBinScanTag (AsnIoPtr aip)
419 {
420 	Int4 used;
421 	Uint4 number;
422 	Int2 bytes, lenbytes;
423 	BytePtr bp;
424 	Byte octet, bit8_7, bit5_1;
425 	Boolean bit6;
426 
427 	used = 0;             /* no bytes read yet */
428 	if (aip->tagsaved)    /* return currently saved tag */
429 	{
430 		aip->tagsaved = FALSE;
431 		return used;        /* no additional bytes read */
432 	}
433 
434 	bytes = aip->bytes - aip->offset;    /* current location in buffer */
435 	if (! bytes)
436 	{
437 		bytes = AsnIoReadBlock(aip);
438 		if (bytes == 0)
439 			return ASNDEBIN_EOF;
440 	}
441 	bp = aip->buf + aip->offset;
442 
443 						/*** read first octet of tag-id ******/
444 	octet = *bp;
445 	bp++; bytes--; used++;
446 
447 	bit5_1 	= octet & (Byte)0x1f;    /* short form tag number */
448 	bit6 = (Byte)((octet >> 5) & 0x01);     /*  constructed? */
449 	bit8_7 = (Byte)((octet >> 6) & 0x03);   /* tag class */
450 
451 	switch (bit8_7)         /* get tag class */
452 	{
453 		case 0x0:
454 			aip->tagclass = TAG_UNIVERSAL;
455 			break;
456 		case 0x1:
457 			aip->tagclass = TAG_APPLICATION;
458 			break;
459 		case 0x2:
460 			aip->tagclass = TAG_CONTEXT;
461 			break;
462 		case 0x3:
463 			aip->tagclass = TAG_PRIVATE;
464 			break;
465 	}
466 
467 	aip->constructed = bit6;     /* constructed? */
468 
469 							/*** get the tag-id ****/
470 	if (bit5_1 != 0x1f)    /* short form */
471 	{
472 		aip->tagnumber = bit5_1;    /* that's it */
473 	}
474 	else                   /* long form */
475 	{
476 		number = 0;     /* have to build it up */
477 		do
478 		{
479 			if (! bytes)
480 			{
481 				bytes = AsnIoReadBlock(aip);
482                 if (! bytes)
483                     {AsnIoErrorMsg(aip, 17); return 0;}
484 				bp = aip->buf;
485 			}
486 			octet = *bp;
487 			bp++; bytes--; used++;
488 			number = (number << 7) + (octet & 0x7f);
489 		}
490 		while ((octet & 0x80) != 0);
491 		aip->tagnumber = (Int2) number;
492 	}
493 
494 								/*** scan the length, if present */
495 	if (! bytes)
496 	{
497 		bytes = AsnIoReadBlock(aip);
498         if (! bytes)
499              {AsnIoErrorMsg(aip, 17); return 0;}
500 		bp = aip->buf;
501 	}
502 
503 	octet = *bp;
504 	bp++; bytes--; used++;
505 
506 	if (! (octet & 0x80))             /* short form used */
507 		aip->length = octet & 0x7f;
508 	else if ((octet & 0x7f) == 0x00)    /* indefinate form used */
509 		aip->length = INDEFINATE;
510 	else                                 /* long form used */
511 	{
512 		number = 0;
513 		for (lenbytes = (Int2)(octet & 0x7f); lenbytes > 0; lenbytes--)
514 		{
515 			if (! bytes)
516 			{
517 				bytes = AsnIoReadBlock(aip);
518                 if (! bytes)
519                     {AsnIoErrorMsg(aip, 17); return 0;}
520 				bp = aip->buf;
521 			}
522 			octet = *bp;
523 			bp++; bytes--; used++;
524 			number = (number << 8) + octet;
525 		}
526 		aip->length = number;
527 	}
528 
529 	aip->offset = aip->bytes - bytes;
530 	aip->used = used;
531 	return used;
532 }
533 
534 /*****************************************************************************
535 *
536 *   Int2 AsnBinReadVal(aip, atp, valueptr)
537 *   	read the value pointed at by atp
538 *         this should be the same as aip->typestack[aip->type_indent].type
539 *   	returns START_STRUCT
540 *               END_STRUCT
541 *   			1 if ok
542 *   			0 if an error occurred
543 *   	if (valueptr == NULL)
544 *   		just checks that value is of proper type
545 *
546 *****************************************************************************/
547 static CharPtr AsnDeBinReadStringUTF8 (AsnIoPtr aip, AsnTypePtr atp);
548 
AsnBinReadVal(AsnIoPtr aip,AsnTypePtr atp,DataValPtr valueptr)549 NLM_EXTERN Int2 LIBCALL  AsnBinReadVal (AsnIoPtr aip, AsnTypePtr atp, DataValPtr valueptr)
550 {
551 	Int4 used;
552 	Int2 isa, retval;
553 	Boolean terminalvalue;      /* set if read a terminal value */
554 	AsnTypePtr atp2;
555 	Boolean read_value;
556 	DataVal fake_value;
557 	AsnTypePtr base_type, curr_type;
558 	int next_type;
559     PstackPtr currpsp, prevpsp;
560 
561 	currpsp = & aip->typestack[aip->type_indent];
562     curr_type = currpsp->type;
563     if (aip->type_indent)
564         prevpsp = currpsp - 1;
565     else
566         prevpsp = NULL;
567 
568 	if (atp == NULL)
569 		return 0;
570 
571 	base_type = AsnFindBaseType(atp);
572     if (base_type == NULL)     /* not found */
573     {
574         base_type = atp;
575         while (base_type->type != NULL)
576             base_type = base_type->type;
577         if (base_type->imported)
578 		{
579             AsnIoErrorMsg(aip,9, AsnErrGetTypeName(atp->name), AsnErrGetTypeName(base_type->name));
580 			return 0;
581 		}
582        else
583 		{
584             AsnIoErrorMsg(aip,10, AsnErrGetTypeName(atp->name), AsnErrGetTypeName(base_type->name));
585 			return 0;
586 		}
587     }
588 	isa = base_type->type->isa;
589 
590 	if (valueptr == NULL)       /* just check the value */
591 	{
592 		read_value = FALSE;
593 		valueptr = &fake_value;
594 	}
595 	else
596 		read_value = TRUE;
597 
598 	retval = 1;       /* normal return */
599 	terminalvalue = TRUE;    /* most values are terminal values */
600 
601 	if (ISA_STRINGTYPE(isa) && isa != UTF8STRING_TYPE)
602 		isa = GENERALSTRING_TYPE;
603 
604 	switch (isa)
605 	{
606 		case SEQ_TYPE:
607 		case SET_TYPE:
608 		case SETOF_TYPE:
609 		case SEQOF_TYPE:
610 			terminalvalue = FALSE;  /* handled by AsnTypeSetIndent() */
611 			if ((prevpsp == NULL) || (! prevpsp->resolved))   /* open brace */
612 			{
613 				AsnTypeSetIndent(TRUE, aip, atp);
614 				while (aip->tagclass != TAG_UNIVERSAL)  /* read to struct */
615 				{
616 					used = AsnDeBinScanTag(aip);
617 					if (! AsnDeBinDecr(used, aip))
618 						return 0;
619 				}
620 				retval = START_STRUCT;
621 				valueptr->intvalue = START_STRUCT;
622 				terminalvalue = FALSE;
623 			}
624 			else
625 			{			   /* close brace already read in AsnBinReadId */
626 				switch (isa)
627 				{
628 					case SEQOF_TYPE:
629 					case SETOF_TYPE:
630 						break;
631 					case SEQ_TYPE:       /* check that no more waiting */
632         				if (curr_type != NULL)   /* check next one */
633 		        			atp2 = curr_type->next;
634 				        else                     /* empty sequence written */
635         					atp2 = (AsnTypePtr) base_type->branch;
636 						while (atp2 != NULL)
637 						{
638 							if (! (atp2->optional || atp2->hasdefault))
639 							{
640 								AsnIoErrorMsg(aip, 7, AsnErrGetTypeName(atp2->name), AsnErrGetTypeName(atp->name));
641 								return 0;
642 							}
643 							atp2 = atp2->next;
644 						}
645 						break;
646 					default:
647 						break;
648 				}
649 				next_type = aip->type_indent - 2;   /* end any choices */
650 				while ((next_type >= 0) &&
651 					(AsnFindBaseIsa(aip->typestack[next_type].type) == CHOICE_TYPE))
652 				{
653                     currpsp = & aip->typestack[next_type];
654                     atp2 = currpsp->type;
655 					if ((atp2->tagclass != TAG_NONE) &&
656 						(currpsp->tag_indef))
657 					{
658 						used = AsnDeBinScanTag(aip);   /* should be 00 for tag */
659 						if (! AsnDeBinDecr(used, aip))
660 							return 0;
661 						if ((aip->length == 0) && (aip->tagclass == 0) &&
662 							(aip->tagnumber == 0))
663 							currpsp->tag_indef = FALSE;
664 						else
665 						{
666 							AsnIoErrorMsg(aip, 3, AsnErrGetTypeName(atp2->name));
667 							return 0;
668 						}
669 					}
670 					next_type--;
671 				}
672 				AsnTypeSetIndent(FALSE, aip, curr_type);
673 				retval = END_STRUCT;
674 				valueptr->intvalue = END_STRUCT;
675 			}
676 			break;
677 		case CHOICE_TYPE:
678 			AsnTypeSetIndent(TRUE, aip, atp);  /* nest down to type */
679 			terminalvalue = FALSE;
680 			break;
681 		default:           /* set up for primitive type */
682 			base_type = AsnFindBaseType(atp);
683 			base_type = base_type->type;        /* point at the type itself */
684 
685             RelaxVisibleStringUTF8 (aip, base_type);
686 
687 			while ((aip->tagclass != base_type->tagclass) ||
688 				(aip->tagnumber != base_type->tagnumber))/* read to element */
689 			{
690 				used = AsnDeBinScanTag(aip);
691 				if (! AsnDeBinDecr(used, aip))
692 					return 0;
693 
694                 RelaxVisibleStringUTF8 (aip, base_type);
695 			}
696 
697 			if ((aip->bytes - aip->offset) == 0)
698             {
699                 if (! AsnIoReadBlock(aip))
700                     {AsnIoErrorMsg(aip, 17); return 0;}
701             }
702 			switch (isa)
703 			{
704 				case BOOLEAN_TYPE:
705 					valueptr->boolvalue = AsnDeBinReadBoolean(aip, atp);
706 					break;
707 				case INTEGER_TYPE:
708 					valueptr->intvalue = AsnDeBinReadBigInt(aip, atp);
709 					break;
710 				case ENUM_TYPE:
711 					valueptr->intvalue = AsnDeBinReadInteger(aip, atp);
712 					break;
713 				case BIGINT_TYPE:
714                                         valueptr->bigintvalue = AsnDeBinReadBigInt(aip, atp);
715                                         break;
716 				case REAL_TYPE:
717 					valueptr->realvalue = AsnDeBinReadReal(aip);
718 					break;
719 				case GENERALSTRING_TYPE:
720 					if (read_value)
721 					{
722 						valueptr->ptrvalue = AsnDeBinReadString(aip, atp);
723 						if (valueptr->ptrvalue == NULL)
724 							return 0;
725 					}
726 					else
727 						AsnDeBinSkipString(aip);
728 					break;
729 				case UTF8STRING_TYPE:
730 					if (read_value)
731 					{
732 						valueptr->ptrvalue = AsnDeBinReadStringUTF8(aip, atp);
733 						if (valueptr->ptrvalue == NULL)
734 							return 0;
735 					}
736 					else
737 						AsnDeBinSkipString(aip);
738 					break;
739 				case NULL_TYPE:
740 					AsnDeBinReadNull(aip, atp);
741 					break;
742 				case OCTETS_TYPE:
743 				case STRSTORE_TYPE:
744 					if (read_value)
745 					{
746 						valueptr->ptrvalue = AsnDeBinReadOctets(aip);
747 						if (valueptr->ptrvalue == NULL) return 0;
748 					}
749 					else
750 						AsnDeBinSkipOctets(aip);
751 					break;
752 				default:
753 					AsnIoErrorMsg(aip, 11, AsnErrGetTypeName(atp->name));
754 					return 0;
755 			}
756 			if (currpsp->tag_indef)     /* indefinate user tag */
757 			{
758 				used = AsnDeBinScanTag(aip);   /* should be 00 for tag */
759 				if (! AsnDeBinDecr(used, aip))
760 					return 0;
761 				if ((aip->length == 0) && (aip->tagclass == 0) &&
762 					(aip->tagnumber == 0))
763 					currpsp->tag_indef = FALSE;
764 				else
765 				{
766 					AsnIoErrorMsg(aip, 3, AsnErrGetTypeName(atp->name));
767 					return 0;
768 				}
769 			}
770 	}
771 
772 	if (terminalvalue)       /* pop out of any CHOICE nests */
773 	{
774 	  	next_type = aip->type_indent - 1;   /* end any choices */
775 		if ((next_type >= 0) &&
776 			(AsnFindBaseIsa(aip->typestack[next_type].type) == CHOICE_TYPE))
777 		{
778 			while ((next_type >= 0) &&
779 				(AsnFindBaseIsa(aip->typestack[next_type].type) == CHOICE_TYPE))
780 			{
781                 currpsp = & aip->typestack[next_type];
782 				atp2 = currpsp->type;
783 				if ((curr_type->tagclass != TAG_NONE) &&
784 					(currpsp->tag_indef))
785 				{
786 					used = AsnDeBinScanTag(aip);   /* should be 00 for tag */
787 					if (! AsnDeBinDecr(used, aip))
788 						return 0;
789 					if ((aip->length == 0) && (aip->tagclass == 0) &&
790 						(aip->tagnumber == 0))
791 						currpsp->tag_indef = FALSE;
792 					else
793 					{
794 						AsnIoErrorMsg(aip, 3, AsnErrGetTypeName(atp2->name));
795 						return 0;
796 					}
797 				}
798 				next_type--;
799 			}
800 			AsnTypeSetIndent(FALSE, aip, curr_type);
801 		}
802 	}
803 
804 	return retval;
805 }
806 
807 /*****************************************************************************
808 *
809 *   AsnTypePtr AsnDeBinFindType(aip, amp)
810 *   	returns pointer to type definition in amp
811 *   	or NULL if not found
812 *
813 *****************************************************************************/
AsnDeBinFindType(AsnIoPtr aip,AsnModulePtr amp)814 NLM_EXTERN AsnTypePtr AsnDeBinFindType (AsnIoPtr aip, AsnModulePtr amp)
815 {
816 	AsnTypePtr atp;
817 
818 	while (amp != NULL)
819 	{
820 		atp = AsnDeBinFindElement(aip, amp->types);
821 		if (atp != NULL)
822 			return atp;
823 
824 		amp = amp->next;
825 	}
826 	return NULL;
827 }
828 
829 /*****************************************************************************
830 *
831 *   AsnTypePtr AsnDeBinFindElement(aip, atp)
832 *   	finds an element in a list of elements
833 *   	(elements of SEQ, SET, CHOICE)
834 *
835 *****************************************************************************/
AsnDeBinFindElement(AsnIoPtr aip,AsnTypePtr atp)836 NLM_EXTERN AsnTypePtr AsnDeBinFindElement (AsnIoPtr aip, AsnTypePtr atp)
837 {
838 	while (atp != NULL)
839 	{
840         RelaxVisibleStringUTF8 (aip, atp);
841 
842 		if ((aip->tagclass == atp->tagclass) &&
843 			(aip->tagnumber == atp->tagnumber))
844 			return atp;
845 		else
846 			atp = atp->next;
847 	}
848 	return NULL;
849 }
850 
851 
852 /*****************************************************************************
853 *
854 *   Int4 AsnDeBinReadInteger(aip, atp)
855 *   	expects an INTEGER or ENUMERATED next
856 *   	assumes none of it has already been read
857 *   	does not advance to next token
858 *   	atp points to the definition of this integer for named values
859 *
860 *****************************************************************************/
AsnDeBinReadInteger(AsnIoPtr aip,AsnTypePtr atp)861 NLM_EXTERN Int4 AsnDeBinReadInteger (AsnIoPtr aip, AsnTypePtr atp)
862 {
863 	Int2 bytes, len;
864 	Uint4 number;
865 	BytePtr bp;
866 	AsnValxNodePtr avnp;
867 	Int4 value;
868     AsnTypePtr atp2;
869 
870 	bytes = aip->bytes - aip->offset;
871 	bp = aip->buf + aip->offset;
872 	len = (Int2) aip->length;
873 	aip->tagsaved = FALSE;
874 
875 	if ((*bp & 0x80) != 0)      /* negative number */
876 		number = (Uint4)(-1);
877 	else
878 		number = 0;
879 
880 	while (len)
881 	{
882 		number = (number << 8) | (*bp & 0xff);
883 		bp++; bytes--; len--;
884 		if (! bytes)
885 		{
886 			bytes = AsnIoReadBlock(aip);
887             if (! bytes)
888                 {AsnIoErrorMsg(aip, 17); return 0;}
889 			bp = aip->buf;
890 		}
891 	}
892 
893 	value = (Int4) number;
894 
895 	if (! AsnDeBinDecr(aip->length, aip))
896 		return 0;
897 	aip->offset = aip->bytes - bytes;
898 
899 	if (AsnFindBaseIsa(atp) != ENUM_TYPE)
900 		return value;
901 
902 			/******************** read a named integer value *********/
903 
904     atp2 = AsnFindBaseType(atp);
905 	if (atp2->branch != NULL)       /* named values */
906 	{
907 		avnp = (AsnValxNodePtr) atp2->branch;
908 		while (avnp != NULL)
909 		{
910 			if (avnp->intvalue == value)
911 				return value;
912 			avnp = avnp->next;
913 		}
914 	}
915 
916 	AsnIoErrorMsg(aip, 12, value, AsnErrGetTypeName(atp->name));
917 
918 	return 0;
919 }
920 
921 /*****************************************************************************
922 *
923 *   Int8 AsnDeBinReadBigInt(aip, atp)
924 *   	expects an INTEGER next
925 *   	assumes none of it has already been read
926 *   	does not advance to next token
927 *   	atp points to the definition of this integer for named values
928 *
929 *****************************************************************************/
AsnDeBinReadBigInt(AsnIoPtr aip,AsnTypePtr atp)930 NLM_EXTERN Int8 AsnDeBinReadBigInt (AsnIoPtr aip, AsnTypePtr atp)
931 {
932 	Int2 bytes, len;
933 	Uint8 number;
934 	BytePtr bp;
935 	AsnValxNodePtr avnp;
936 	Int8 value;
937     AsnTypePtr atp2;
938 
939 	bytes = aip->bytes - aip->offset;
940 	bp = aip->buf + aip->offset;
941 	len = (Int2) aip->length;
942 	aip->tagsaved = FALSE;
943 
944 	if ((*bp & 0x80) != 0)      /* negative number */
945 		number = (Uint8)(-1);
946 	else
947 		number = 0;
948 
949 	while (len)
950 	{
951 		number = (number << 8) | (*bp & 0xff);
952 		bp++; bytes--; len--;
953 		if (! bytes)
954 		{
955 			bytes = AsnIoReadBlock(aip);
956             if (! bytes)
957                 {AsnIoErrorMsg(aip, 17); return 0;}
958 			bp = aip->buf;
959 		}
960 	}
961 
962 	value = (Int8) number;
963 
964 	if (! AsnDeBinDecr(aip->length, aip))
965 		return 0;
966 	aip->offset = aip->bytes - bytes;
967 
968 	if (AsnFindBaseIsa(atp) != ENUM_TYPE)
969 		return value;
970 
971 			/******************** read a named integer value *********/
972 
973     atp2 = AsnFindBaseType(atp);
974 	if (atp2->branch != NULL)       /* named values */
975 	{
976 		avnp = (AsnValxNodePtr) atp2->branch;
977 		while (avnp != NULL)
978 		{
979 			if (avnp->intvalue == value)
980 				return value;
981 			avnp = avnp->next;
982 		}
983 	}
984 
985 	AsnIoErrorMsg(aip, 12, value, AsnErrGetTypeName(atp->name));
986 
987 	return (Int8)0;
988 }
989 
990 /*****************************************************************************
991 *
992 *   Boolean AsnDeBinReadBoolean(aip, atp)
993 *   	expects a BOOLEAN next
994 *   	assumes none of it has already been read
995 *   	does not advance to next token
996 *   	atp points to the definition of this BOOLEN
997 *
998 *****************************************************************************/
AsnDeBinReadBoolean(AsnIoPtr aip,AsnTypePtr atp)999 NLM_EXTERN Boolean AsnDeBinReadBoolean (AsnIoPtr aip, AsnTypePtr atp)
1000 {
1001 	BytePtr bp;
1002 	Byte octet;
1003 	Boolean result = TRUE;
1004 
1005 	aip->tagsaved = FALSE;
1006 	if (aip->length != 1)
1007 	{
1008 		AsnIoErrorMsg(aip, 13, AsnErrGetTypeName(atp->name));
1009 		return FALSE;
1010 	}
1011 
1012 	bp = aip->buf + aip->offset;
1013 	octet = *bp;
1014 
1015 	if (octet == 0)
1016 		result = FALSE;
1017 	else
1018 		result = TRUE;
1019 
1020 	aip->offset++;
1021 	AsnDeBinDecr((Int4)1, aip);
1022 
1023 	return result;
1024 }
1025 
1026 /*****************************************************************************
1027 *
1028 *   Int4 AsnDeBinReadString(aip, atp)
1029 *   	expects any String type next
1030 *   	assumes none of it has already been read
1031 *   	does not advance to next token
1032 *   	atp points to the definition of this String
1033 *   	packs String to single value, if segmented on input
1034 *
1035 *****************************************************************************/
AsnDeBinReadStringEx(AsnIoPtr aip,AsnTypePtr atp,Uint1 fix_non_print)1036 static CharPtr AsnDeBinReadStringEx (AsnIoPtr aip, AsnTypePtr atp, Uint1 fix_non_print)
1037 {
1038 	Int4 len;
1039 	register int bytes, amount;
1040 	register BytePtr bp;
1041 	register CharPtr tmp;
1042 	CharPtr result;
1043 
1044 	aip->tagsaved = FALSE;
1045 	len = aip->length;
1046 	AsnDeBinDecr(len, aip);
1047 	result = (CharPtr) MemGet((size_t)(len + 1), FALSE);
1048 	if (result == NULL)
1049 	{
1050 		AsnIoErrorMsg(aip, 14, len, AsnErrGetTypeName(atp->name));
1051 		return NULL;
1052 	}
1053 	result[len] = '\0';
1054 
1055 	bp = aip->buf + aip->offset;
1056 	bytes = (int)(aip->bytes - aip->offset);
1057 	tmp = result;
1058 
1059 	while (len)
1060 	{
1061 		if ((Int4)bytes >= len)
1062 			amount = (int) len;
1063 		else
1064 			amount = bytes;
1065 		bytes -= amount;
1066 		len -= (Int4)amount;
1067 		while (amount)
1068 		{
1069 			if ((fix_non_print != 2) && ((* bp < ' ') || (*bp > '~')))
1070 			{
1071 				*tmp = '\0';
1072 				if ((fix_non_print == 0) || (fix_non_print == 3))
1073 				{
1074 					AsnIoErrorMsg(aip, 106, (int)(*bp), result);
1075 				}
1076 				*bp = '#';   /* repair string with # */
1077 			}
1078 			*tmp = *bp;
1079 			tmp++; bp++; amount--;
1080 		}
1081 		if (! bytes)
1082 		{
1083 			bytes = (int) AsnIoReadBlock(aip);
1084             if (! bytes)
1085                 {AsnIoErrorMsg(aip, 17); return NULL;}
1086 			bp = aip->buf;
1087 		}
1088 	}
1089 	aip->offset = aip->bytes - (Int2) bytes;
1090 	return result;
1091 }
1092 
AsnDeBinReadString(AsnIoPtr aip,AsnTypePtr atp)1093 NLM_EXTERN CharPtr AsnDeBinReadString (AsnIoPtr aip, AsnTypePtr atp)
1094 
1095 {
1096   return AsnDeBinReadStringEx (aip, atp, aip->fix_non_print);
1097 }
1098 
AsnDeBinReadStringUTF8(AsnIoPtr aip,AsnTypePtr atp)1099 static CharPtr AsnDeBinReadStringUTF8 (AsnIoPtr aip, AsnTypePtr atp)
1100 
1101 {
1102   return AsnDeBinReadStringEx (aip, atp, 2);
1103 }
1104 
1105 /*****************************************************************************
1106 *
1107 *   void AsnDeBinSkipString(aip)
1108 *   	expects any String type next
1109 *   	assumes none of it has already been read
1110 *   	does not advance to next token
1111 *   	just reads past end of string
1112 *
1113 *****************************************************************************/
AsnDeBinSkipString(AsnIoPtr aip)1114 NLM_EXTERN void AsnDeBinSkipString (AsnIoPtr aip)
1115 {
1116 	Int4 len;
1117 	register int bytes, amount;
1118 	register BytePtr bp, tmp;
1119 	int bad;
1120 
1121 	aip->tagsaved = FALSE;
1122 	len = aip->length;
1123 	AsnDeBinDecr(len, aip);
1124 
1125 	bp = aip->buf + aip->offset;
1126 	tmp = bp;
1127 	bytes = (int)(aip->bytes - aip->offset);
1128 
1129 	while (len)
1130 	{
1131 		if ((Int4)bytes >= len)
1132 			amount = (int) len;
1133 		else
1134 			amount = bytes;
1135 		bytes -= amount;
1136 		len -= (Int4)amount;
1137 		while (amount)
1138 		{
1139 			if ((* bp < ' ') || (*bp > '~'))
1140 			{
1141 				bad = (int)(*bp);
1142 				*bp = '\0';
1143 				AsnIoErrorMsg(aip, 106, bad, (CharPtr)tmp);
1144 				aip->io_failure = TRUE;
1145 			}
1146 			bp++; amount--;
1147 		}
1148 		if (! bytes)
1149 		{
1150 			bytes = (int) AsnIoReadBlock(aip);
1151             if (! bytes)
1152                 {AsnIoErrorMsg(aip, 17); return;}
1153 			bp = aip->buf;
1154 			tmp = bp;
1155 		}
1156 	}
1157 	aip->offset = aip->bytes - (Int2) bytes;
1158 	return;
1159 }
1160 
1161 /*****************************************************************************
1162 *
1163 *    AsnDeBinReadOctets(aip)
1164 *   	expects any OCTETS type next
1165 *   	assumes none of it has already been read
1166 *   	does not advance to next token
1167 *
1168 *****************************************************************************/
AsnDeBinReadOctets(AsnIoPtr aip)1169 NLM_EXTERN ByteStorePtr AsnDeBinReadOctets (AsnIoPtr aip)
1170 {
1171 	Int4 len;
1172 	Int2 bytes, amount;
1173 	BytePtr bp;
1174 	ByteStorePtr bsp;
1175 
1176 	aip->tagsaved = FALSE;
1177 	len = aip->length;
1178 	AsnDeBinDecr(len, aip);
1179 	bsp = BSNew((Uint4)len);
1180 	if (bsp == NULL) return bsp;
1181 
1182 	bp = aip->buf + aip->offset;
1183 	bytes = aip->bytes - aip->offset;
1184 
1185 	while (len)
1186 	{
1187 		if ((Int4)bytes >= len)
1188 			amount = (Int2) len;
1189 		else
1190 			amount = bytes;
1191 		BSWrite(bsp, bp, amount);
1192 		len -= amount;
1193 		bytes -= amount;
1194 		if (! bytes)
1195 		{
1196 			bytes = AsnIoReadBlock(aip);
1197             if (! bytes)
1198                 {AsnIoErrorMsg(aip, 17); return NULL;}
1199 			bp = aip->buf;
1200 		}
1201 	}
1202 	aip->offset = aip->bytes - bytes;
1203 	return bsp;
1204 }
1205 
1206 /*****************************************************************************
1207 *
1208 *    AsnDeBinSkipOctets(aip)
1209 *   	expects any OCTETS type next
1210 *   	assumes none of it has already been read
1211 *   	does not advance to next token
1212 *
1213 *****************************************************************************/
AsnDeBinSkipOctets(AsnIoPtr aip)1214 NLM_EXTERN void AsnDeBinSkipOctets (AsnIoPtr aip)
1215 {
1216 	Int4 len;
1217 	Int2 bytes, amount;
1218 
1219 	aip->tagsaved = FALSE;
1220 	len = aip->length;
1221 	AsnDeBinDecr(len, aip);
1222 
1223 	bytes = aip->bytes - aip->offset;
1224 
1225 	while (len)
1226 	{
1227 		if ((Int4)bytes >= len)
1228 			amount = (Int2) len;
1229 		else
1230 			amount = bytes;
1231 		len -= amount;
1232 		bytes -= amount;
1233 		if (! bytes)
1234 		{
1235 			bytes = AsnIoReadBlock(aip);
1236             if (! bytes)
1237                 {AsnIoErrorMsg(aip, 17); return ;}
1238 		}
1239 	}
1240 	aip->offset = aip->bytes - bytes;
1241 	return;
1242 }
1243 
1244 /*****************************************************************************
1245 *
1246 *   FloatHi AsnDeBinReadReal(aip)
1247 *   	expects a REAL next
1248 *   	assumes none of it has already been read
1249 *   	does not advance to next token
1250 *
1251 *****************************************************************************/
AsnDeBinReadReal(AsnIoPtr aip)1252 NLM_EXTERN FloatHi AsnDeBinReadReal (AsnIoPtr aip)
1253 {
1254 	double result = 0.0;
1255 	Int4 len;
1256 	Int2 bytes, amount;
1257 	BytePtr bp;
1258 	char buf[200], *tmp;
1259 
1260 	aip->tagsaved = FALSE;
1261 	len = aip->length;
1262 	AsnDeBinDecr(len, aip);
1263 
1264 	bp = aip->buf + aip->offset;
1265 	bytes = aip->bytes - aip->offset;
1266 	tmp = buf;
1267 
1268 	while (len)
1269 	{
1270 		if ((Int4)bytes >= len)
1271 			amount = (Int2) len;
1272 		else
1273 			amount = bytes;
1274 		MemCopy(tmp, bp, (size_t)amount);
1275 		tmp += amount;
1276 		len -= amount;
1277 		bytes -= amount;
1278 		if (! bytes)
1279 		{
1280 			bytes = AsnIoReadBlock(aip);
1281             if (! bytes)
1282                 {AsnIoErrorMsg(aip, 17); return (FloatHi)result;}
1283 			bp = aip->buf;
1284 		}
1285 	}
1286 	aip->offset = aip->bytes - bytes;
1287 
1288 	if (buf[0] != '\0')        /* not decimal encoding */
1289 	{
1290 		AsnIoErrorMsg(aip, 15);
1291 		return (FloatHi)result;
1292 	}
1293 
1294 	*tmp = '\0';
1295 	                         /* range check base 10 exponents assuming doubles */
1296 
1297 	if ((tmp = StringStr((buf+1), "e")) != NULL)
1298 	{
1299 		int n = atoi(tmp + 1);
1300 		if (n < DBL_MIN_10_EXP)     /** too small, return 0.0 **/
1301 			return (FloatHi)result;
1302 		else if (n > DBL_MAX_10_EXP)   /** too big, return the max */
1303 			return (FloatHi)DBL_MAX;
1304 	}
1305 
1306 	if (sscanf((buf + 1), "%lf", &result) != 1) {
1307 		result = 0.0;
1308 	}
1309 	return (FloatHi)result;
1310 }
1311 
1312 /*****************************************************************************
1313 *
1314 *   void AsnDeBinReadNull(aip, atp)
1315 *
1316 *****************************************************************************/
AsnDeBinReadNull(AsnIoPtr aip,AsnTypePtr atp)1317 NLM_EXTERN void AsnDeBinReadNull (AsnIoPtr aip, AsnTypePtr atp)
1318 {
1319 	aip->tagsaved = FALSE;
1320 	if (aip->length != 0)
1321 		AsnIoErrorMsg(aip, 16, AsnErrGetTypeName(atp->name));
1322 
1323 	return;
1324 }
1325 
1326 /*****************************************************************************
1327 *
1328 *   void AsnDeBinSkipStruct(aip)
1329 *   	skips current structure and all substructures
1330 *       Does NOT read following element
1331 *
1332 *****************************************************************************/
AsnDeBinSkipStruct(AsnIoPtr aip)1333 NLM_EXTERN void AsnDeBinSkipStruct (AsnIoPtr aip)
1334 {
1335 	aip->tagsaved = FALSE;
1336 	AsnIoErrorMsg(aip, 0);
1337 	return;
1338 }
1339 
1340