if (!decodeOptions->suppressContent) { SECItem *item = (sitem.data) ? &sitem : NSS_CMSMessage_GetContent(cmsg); SECITEM_CopyItem(NULL, output, item);
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); }
decode(FILE *out, SECItem *output, SECItem *input,        const struct decodeOptionsStr *decodeOptions){    NSSCMSDecoderContext *dcx;    NSSCMSMessage *cmsg;    NSSCMSContentInfo *cinfo;    NSSCMSSignedData *sigd = NULL;    NSSCMSEnvelopedData *envd;    NSSCMSEncryptedData *encd;    int nlevels, i, nsigners, j;    char *signercn;    NSSCMSSignerInfo *si;    SECOidTag typetag;    SECItem **digests;    SECItem sitem = { 0, 0, 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++) {	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:	    if (decodeOptions->headerLevel >= 0)		fprintf(out, "type=signedData; ");	    sigd = (NSSCMSSignedData *)NSS_CMSContentInfo_GetContent(cinfo);	    if (sigd == NULL) {		SECU_PrintError(progName, 		                "problem finding signedData component");		goto loser;	    }	    /* if we have a content file, but no digests for this signedData */	    if (decodeOptions->contentFile != NULL && 	        !NSS_CMSSignedData_HasDigests(sigd)) {		PLArenaPool     *poolp;		SECAlgorithmID **digestalgs;		/* detached content: grab content file */		if (!sitem.data) {		    SECU_FileToItem(&sitem, decodeOptions->contentFile);		}		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, 	                                   PR_FALSE) 	          != 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) {		/* must be a cert transport message */		SECStatus rv;		/* XXX workaround for bug #54014 */		NSS_CMSSignedData_ImportCerts(sigd,                                             decodeOptions->options->certHandle, 		                            decodeOptions->options->certUsage, 		                            PR_TRUE);		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++) {		SECStatus bad;		NSSCMSVerificationStatus vs;		const char * svs;		si = NSS_CMSSignedData_GetSignerInfo(sigd, j);		signercn = NSS_CMSSignerInfo_GetSignerCommonName(si);		if (signercn == NULL)		    signercn = "";		if (decodeOptions->headerLevel >= 0)		    fprintf(out, "\n\t\tsigner%d.id=\"%s\"; ", j, 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:	    if (decodeOptions->headerLevel >= 0)		fprintf(out, "type=envelopedData; ");	    envd = (NSSCMSEnvelopedData *)NSS_CMSContentInfo_GetContent(cinfo);	    break;	case SEC_OID_PKCS7_ENCRYPTED_DATA:	    if (decodeOptions->headerLevel >= 0)		fprintf(out, "type=encryptedData; ");	    encd = (NSSCMSEncryptedData *)NSS_CMSContentInfo_GetContent(cinfo);	    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) {	SECItem *item = (sitem.data) 	                    ? &sitem 	                    : NSS_CMSMessage_GetContent(cmsg);	SECITEM_CopyItem(NULL, output, item);    }    return cmsg;loser:    if (cmsg)	NSS_CMSMessage_Destroy(cmsg);    return NULL;}