PORT_FreeArena(poolp, PR_FALSE);
decode(FILE *out, SECItem *input, const struct decodeOptionsStr *decodeOptions){    NSSCMSDecoderContext *dcx;    NSSCMSMessage *cmsg;    int nlevels, i;    SECItem sitem = { 0, 0, 0 };    PORT_SetError(0);    dcx = NSS_CMSDecoder_Start(NULL,                                NULL, NULL,         /* content callback     */                               pwcb, pwcb_arg,     /* password callback    */			       decodeOptions->dkcb, /* decrypt key callback */                               decodeOptions->bulkkey);    (void)NSS_CMSDecoder_Update(dcx, (char *)input->data, input->len);    cmsg = NSS_CMSDecoder_Finish(dcx);    if (cmsg == NULL) {	fprintf(stderr, "%s: failed to decode message.\n", progName);	return NULL;    }    if (decodeOptions->headerLevel >= 0) {	/*fprintf(out, "SMIME: ", decodeOptions->headerLevel, i);*/	fprintf(out, "SMIME: ");    }    nlevels = NSS_CMSMessage_ContentLevelCount(cmsg);    for (i = 0; i < nlevels; i++) {	NSSCMSContentInfo *cinfo;	SECOidTag typetag;	cinfo = NSS_CMSMessage_ContentLevel(cmsg, i);	typetag = NSS_CMSContentInfo_GetContentTypeTag(cinfo);	if (decodeOptions->headerLevel >= 0)	    fprintf(out, "\tlevel=%d.%d; ", decodeOptions->headerLevel, nlevels - i);	switch (typetag) {	case SEC_OID_PKCS7_SIGNED_DATA:	  {	    NSSCMSSignedData *sigd = NULL;	    SECItem **digests;	    int nsigners;	    int j;	    if (decodeOptions->headerLevel >= 0)		fprintf(out, "type=signedData; ");	    sigd = (NSSCMSSignedData *)NSS_CMSContentInfo_GetContent(cinfo);	    if (sigd == NULL) {		SECU_PrintError(progName, "signedData component missing");		goto loser;	    }	    /* if we have a content file, but no digests for this signedData */	    if (decodeOptions->content.data != NULL && 	        !NSS_CMSSignedData_HasDigests(sigd)) {		PLArenaPool     *poolp;		SECAlgorithmID **digestalgs;		/* detached content: grab content file */		sitem = decodeOptions->content;		if ((poolp = PORT_NewArena(1024)) == NULL) {		    fprintf(stderr, "cmsutil: Out of memory.\n");		    goto loser;		}		digestalgs = NSS_CMSSignedData_GetDigestAlgs(sigd);		if (DigestFile (poolp, &digests, &sitem, digestalgs) 		      != SECSuccess) {		    SECU_PrintError(progName, 		                    "problem computing message digest");		    goto loser;		}		if (NSS_CMSSignedData_SetDigests(sigd, digestalgs, digests) 		    != SECSuccess) {		    		    SECU_PrintError(progName, 		                    "problem setting message digests");		    goto loser;		}		PORT_FreeArena(poolp, PR_FALSE);	    }	    /* import the certificates */	    if (NSS_CMSSignedData_ImportCerts(sigd, 	                                   decodeOptions->options->certHandle, 	                                   decodeOptions->options->certUsage, 	                                   decodeOptions->keepCerts) 	          != SECSuccess) {		SECU_PrintError(progName, "cert import failed");		goto loser;	    }	    /* find out about signers */	    nsigners = NSS_CMSSignedData_SignerInfoCount(sigd);	    if (decodeOptions->headerLevel >= 0)		fprintf(out, "nsigners=%d; ", nsigners);	    if (nsigners == 0) {		/* Might be a cert transport message		** or might be an invalid message, such as a QA test message		** or a message from an attacker.		*/		SECStatus rv;		rv = NSS_CMSSignedData_VerifyCertsOnly(sigd, 		                            decodeOptions->options->certHandle, 		                            decodeOptions->options->certUsage);		if (rv != SECSuccess) {		    fprintf(stderr, "cmsutil: Verify certs-only failed!\n");		    goto loser;		}		return cmsg;	    }	    /* still no digests? */	    if (!NSS_CMSSignedData_HasDigests(sigd)) {		SECU_PrintError(progName, "no message digests");		goto loser;	    }	    for (j = 0; j < nsigners; j++) {		const char * svs;		NSSCMSSignerInfo *si;		NSSCMSVerificationStatus vs;		SECStatus bad;		si = NSS_CMSSignedData_GetSignerInfo(sigd, j);		if (decodeOptions->headerLevel >= 0) {		    char *signercn;		    static char empty[] = { "" };		    signercn = NSS_CMSSignerInfo_GetSignerCommonName(si);		    if (signercn == NULL)			signercn = empty;		    fprintf(out, "\n\t\tsigner%d.id=\"%s\"; ", j, signercn);		    if (signercn != empty)		        PORT_Free(signercn);		}		bad = NSS_CMSSignedData_VerifySignerInfo(sigd, j, 		                           decodeOptions->options->certHandle, 		                           decodeOptions->options->certUsage);		vs  = NSS_CMSSignerInfo_GetVerificationStatus(si);		svs = NSS_CMSUtil_VerificationStatusToString(vs);		if (decodeOptions->headerLevel >= 0) {		    fprintf(out, "signer%d.status=%s; ", j, svs);		    /* goto loser ? */		} else if (bad && out) {		    fprintf(stderr, "signer %d status = %s\n", j, svs);		    goto loser;		}	    }	  }	  break;	case SEC_OID_PKCS7_ENVELOPED_DATA:	  {	    NSSCMSEnvelopedData *envd;	    if (decodeOptions->headerLevel >= 0)		fprintf(out, "type=envelopedData; ");	    envd = (NSSCMSEnvelopedData *)NSS_CMSContentInfo_GetContent(cinfo);	    if (envd == NULL) {		SECU_PrintError(progName, "envelopedData component missing");		goto loser;	    }	  }	  break;	case SEC_OID_PKCS7_ENCRYPTED_DATA:	  {	    NSSCMSEncryptedData *encd;	    if (decodeOptions->headerLevel >= 0)		fprintf(out, "type=encryptedData; ");	    encd = (NSSCMSEncryptedData *)NSS_CMSContentInfo_GetContent(cinfo);	    if (encd == NULL) {		SECU_PrintError(progName, "encryptedData component missing");		goto loser;	    }	  }	  break;	case SEC_OID_PKCS7_DATA:	    if (decodeOptions->headerLevel >= 0)		fprintf(out, "type=data; ");	    break;	default:	    break;	}	if (decodeOptions->headerLevel >= 0)	    fprintf(out, "\n");    }    if (!decodeOptions->suppressContent && out) {	SECItem *item = (sitem.data ? &sitem 	                            : NSS_CMSMessage_GetContent(cmsg));	if (item && item->data && item->len) {	    fwrite(item->data, item->len, 1, out);    	}    }    return cmsg;loser:    if (cmsg)	NSS_CMSMessage_Destroy(cmsg);    return NULL;}