/************************************************************************
*
* Copyright (c) 2003-2004, C&C Research Laboratories, NEC Europe Ltd.
*
* Copyright in this library belongs to C&C Research Laboratories,
* Rathausallee 10, 53757 Sankt Augustin, Germany.
*
* This software may not be used, sold, licensed, transferred, copied
* or reproduced in whole or in part in any manner or form or in or
* on any media by any person other than in accordance with the terms
* of the Licence Agreement supplied with the software, or otherwise
* without the prior written consent of the copyright owners.
*
* This software is distributed WITHOUT ANY WARRANTY, without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE, except where stated in the Licence Agreement supplied with
* the software.
*
*  Created By :           Federico Crazzolara
*  Created for Project :  GEMSS (IST-2001-37153)
*
************************************************************************/


package de.nece.ccrl.transport.soapProcessors;



import java.util.*;
import java.io.*;
import org.apache.axis.encoding.*;
import org.apache.axis.Constants;
import org.apache.axis.Message;
import org.apache.axis.MessageContext;
import org.apache.axis.server.AxisServer;
import javax.xml.soap.Name;
import org.apache.axis.message.PrefixedQName;
import org.apache.commons.codec.binary.Base64;

import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPPart;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.Node;
import javax.xml.soap.AttachmentPart;
import javax.xml.rpc.encoding.TypeMapping;
import java.security.Security;
import java.security.Key;
import java.security.interfaces.RSAPublicKey;
import java.security.interfaces.RSAPrivateKey;
import javax.crypto.SecretKey;
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.CipherInputStream;
import javax.crypto.spec.IvParameterSpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.xml.sax.InputSource;

import de.nece.ccrl.util.*;

import java.util.logging.*;

public class  SimpleWSEncryption {    

 
    private static Logger logger = Logger.getLogger("logging.advancedSecurity");

    public String getKeyOwner(SOAPMessage msg) throws WSEncryptionException {

	Name name;
	
	SOAPPart sp = msg.getSOAPPart();
	SOAPEnvelope envelope = null;
	SOAPBody body = null;
	Iterator i;

	// extract key owner body 

	try{
	    envelope = sp.getEnvelope();
	    body = envelope.getBody();

	    name = new PrefixedQName("http://www.w3.org/2001/04/xmlenc#","EncryptedData","xenc");
	    i = body.getChildElements(name);	    
	    SOAPElement el;

	    if (i.hasNext()) {
		el = (SOAPElement) i.next();		
		name = new PrefixedQName("http://www.w3.org/2000/09/xmldsig#","KeyInfo","ds");
		i = el.getChildElements(name);
		if (i.hasNext()) {
		    el = (SOAPElement) i.next();
		    name = new PrefixedQName("http://www.w3.org/2000/09/xmldsig#","KeyName","ds");
		    i = el.getChildElements(name);
		    if (i.hasNext()){
			
			return ((SOAPElement) i.next()).getValue();
		    }
		}
	    }
	} catch (Exception e) {     
	    logger.log(Level.SEVERE,"Unexpected SOAP processing error",e);
	    throw new WSEncryptionException("Unexpected SOAP processing error");
	}
	
	return null;
    }



    
    public SOAPMessage encrypt(SOAPMessage msg, TypeMapping tm, Key key, String owner, String alg) throws WSEncryptionException {

	Name name;
	String cleartext = null;
	byte[] cleartext_bytes = null;
	byte[] ciphertext_bytes = null;
	String ciphertext = null;
	
	SOAPPart sp = msg.getSOAPPart();
	SOAPEnvelope envelope = null;
	Iterator u;

	Security.addProvider(new BouncyCastleProvider());
	
	org.apache.commons.codec.binary.Base64 codec = new org.apache.commons.codec.binary.Base64();	

	// extract cleartext from original body	

	try{
	    envelope = sp.getEnvelope();
	    SOAPBody body = envelope.getBody();
	    envelope.getBody().detachNode();
	    u = body.getChildElements();
	    

	    // make it an AXIS soap body because has more functionality to extract xml cleartext

	    
	    org.apache.axis.message.SOAPEnvelope ax_env = new org.apache.axis.message.SOAPEnvelope();
	    org.apache.axis.message.SOAPBody ax_body = (org.apache.axis.message.SOAPBody) ax_env.getBody();
	    while (u.hasNext()) {
		ax_body.addChild((org.apache.axis.message.SOAPBodyElement) u.next());
  	    }
	    
	    u = ax_body.getChildElements();


	    // serialize the body contents (can be multiple elements) it into a cleartext string


	    MessageContext msgContext = new MessageContext(new AxisServer());
	    TypeMappingRegistry reg = msgContext.getTypeMappingRegistry();
	    if (tm == null) {
		tm = (TypeMapping) reg.createTypeMapping();
	    }
	    reg.register(Constants.URI_DEFAULT_SOAP_ENC, tm);
	    
	    Writer stringWriter = new StringWriter();
	    SerializationContext context = new SerializationContextImpl(stringWriter,msgContext);
	    context.setDoMultiRefs(false);
	    
	    while (u.hasNext()) {
		try{
		    ((org.apache.axis.message.SOAPBodyElement) u.next()).output(context);
		}catch (Exception e) {e.printStackTrace();}
	    }
	    
	    cleartext = stringWriter.toString();


	    cleartext_bytes = cleartext.getBytes("UTF-8");
	    
	} catch (Exception e) {
	    logger.log(Level.SEVERE,"Unexpected exception when serializing body content into cleartext string",e);
	    throw new WSEncryptionException("Unexpected exception when serializing body content into cleartext string");
	}


	
	// encrypt the cleartext and obtain cyphertext 
        // cleartext is already UTF-8 encoded cos its xml standard
		    
	

	if (key instanceof SecretKey) {
	    if (!(alg.equals("DES"))) throw new WSEncryptionException("Unsupported encryption algorithm"); 

	    try{

		byte[] salt = {(byte)0x8E, 0x12, 0x39, (byte)0x9C,
			       0x07, 0x72, 0x6F, 0x5A};

		
		IvParameterSpec iv = new IvParameterSpec(salt); 
		
		Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding","BC");
		c.init(Cipher.ENCRYPT_MODE,key,iv);
		
		
		ByteArrayOutputStream bOut = new ByteArrayOutputStream();
		CipherOutputStream cOut = new CipherOutputStream(bOut, c);

		ByteArrayInputStream bIn = new ByteArrayInputStream(cleartext_bytes);

		byte[] buf = new byte[1024];
		int numRead = 0;
		while((numRead = bIn.read(buf)) >= 0) {
		    cOut.write(buf,0,numRead);
		}

		cOut.close();
		
		ciphertext = new String(codec.encode(bOut.toByteArray()),"UTF-8");


		// ENCRYPTION OF ATTACHEMENTS. Attachements are retrived, encrypted and again set
		// to the SOAP message.

		Iterator iterator = msg.getAttachments(); 
		AttachmentPart aP;
		InputStream istream;
		byte[] attachment_bytes; 
		byte[] attachment_ciphertext;
		int num;
		String type;
		
		while(iterator.hasNext()) {
		    
		  
		    aP = (AttachmentPart) iterator.next();
		    type = aP.getContentType();
	
		    try{  

			Object content = aP.getContent();
			if (content instanceof String) {
			    istream = new ByteArrayInputStream(((String)content).getBytes());
			} else 
			    if (content instanceof javax.xml.transform.stream.StreamSource) {
				istream = ((javax.xml.transform.stream.StreamSource)content).getInputStream();
			    } else
				if (content instanceof InputStream) {
				    istream = (InputStream) content;
				} else {
				    System.out.println("UNSUPPORTED MIME TYPE for ENCRYPTION");   
				    istream = (InputStream) aP.getContent();
				}

			num = istream.available();	

			
			
			// DO ENCRYPTION 
	
			OutputInputStream pOut = new OutputInputStream();

			FillCryptotext f = new FillCryptotext(istream,pOut,c);
			((Thread)f).start();

			CryptoDataSource cds = new CryptoDataSource(pOut,type);
			javax.activation.DataHandler h = new javax.activation.DataHandler(cds);


			aP.addMimeHeader("encrypted",type);
			aP.setDataHandler(h);

			

		    }catch(Exception e){

			logger.log(Level.SEVERE,"Unexpected symmetric encription fault while processing attachments",e);
			System.out.println(e.getMessage());
			e.printStackTrace();
			throw new WSEncryptionException("Unexpected symmetric encription fault while processing attachments");}
		}




	    } catch (Exception e) {
		logger.log(Level.SEVERE,"Unexpected symmetric encription fault",e);
		System.out.println(e.getMessage());
		e.printStackTrace();
		throw new WSEncryptionException("Unexpected symmetric encription fault");}
	}

	else if (key instanceof RSAPublicKey) {
	    if (!(alg.equals("RSA"))) throw new WSEncryptionException("Unsupported encryption algorithm");

	    try{
		Cipher c = Cipher.getInstance("RSA/ECB/OAEPPadding","BC");
		c.init(Cipher.ENCRYPT_MODE,key);
		
		
		int inblocksize = c.getBlockSize();
		int outblocksize = c.getOutputSize(inblocksize);	
		int cleartextsize = cleartext_bytes.length;
		
		int rest = 0;
		if ((cleartextsize%inblocksize) != 0) {
		    rest = 1;	    
		}
		
		int blocknumber = (cleartextsize/inblocksize)+rest;
		int ciphertextsize = blocknumber*outblocksize;
		ciphertext_bytes = new byte[ciphertextsize];
		
		int finalb = 0;
		if (rest == 1) {
		    finalb = cleartextsize - ((blocknumber-1)*inblocksize);
		}
		
		int i=0,r=0;
		byte[] inblock = new byte[inblocksize];
		byte[] outblock = new byte[outblocksize];
		
		for (i=0;i<blocknumber-1;i=i+1) {     	    
		    
		    for (r=0;r<inblocksize;r=r+1){
			inblock[r] = cleartext_bytes[i*inblocksize + r];
		    }
		    
		    outblock = c.doFinal(inblock);
		    
		    for (r=0;r<outblocksize;r=r+1){
			ciphertext_bytes[i*outblocksize + r] = outblock[r];
		    }
		}
		
		if (finalb!=0) {
		    inblock = new byte[finalb];
		    
		    for (r=0;r<finalb;r=r+1){
			inblock[r] = cleartext_bytes[i*inblocksize + r];
		    }
		    
		    outblock = c.doFinal(inblock);
		    
		    for (r=0;r<outblocksize;r=r+1){
			ciphertext_bytes[i*outblocksize + r] = outblock[r];
		    }
		    
		}
		
		ciphertext = new String(codec.encode(ciphertext_bytes),"UTF-8");

	    } catch (Exception e) {
		logger.log(Level.SEVERE,"Unexpected public-key encryption fault",e);
		throw new WSEncryptionException("Unexpected public-key encryption fault");}	    
	}

	
	else {
	    throw new WSEncryptionException("Unsupported key type");
	}
	
	// adds the soap security header
	try{
	    SOAPHeader header = envelope.getHeader(); // there is a header so can not other otherwise gives exception
	    name = new PrefixedQName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd","Security","wsse");
	    u = header.getChildElements(name);
	    SOAPHeaderElement header_el;
	    if (!(u.hasNext())) {	
		header_el = header.addHeaderElement(name);
	    } else 
		{
		    header_el = (org.apache.axis.message.SOAPHeaderElement) u.next();   
		    //if there is a security header already then take that one  
		    //name = new PrefixedQName("http://docs.oasis","S","w");
		    //header.addHeaderElement(name);
		}
	    name = new PrefixedQName("http://www.w3.org/2001/04/xmlenc#","ReferenceList","xenc");
	    SOAPElement reflist = header_el.addChildElement(name);
	    SOAPElement refdata = reflist.addChildElement("DataReference", "xenc");
	    name = new PrefixedQName(null,"URI",null);
	    refdata.addAttribute(name,"#body"); 
	} catch (SOAPException e) {
	    logger.log(Level.SEVERE,"Unexpected soap header processing fault",e);
	    throw new WSEncryptionException("Unexpected soap header processing fault");
	}

	
	// modifies the soap body substituting the cleartext with the cyphertext
	try{
       
	    SOAPBody encr_body = envelope.addBody();	    
	    
	    // prepare new body elements
	    name = new PrefixedQName("http://www.w3.org/2001/04/xmlenc#","EncryptedData","xenc");
	    SOAPBodyElement body_el = encr_body.addBodyElement(name);
	    name = new PrefixedQName(null,"MimeType",null);
	    body_el.addAttribute(name,"text/xml");
	    name = new PrefixedQName(null,"Id",null);
	    body_el.addAttribute(name,"body");
	    
	    SOAPElement encrmethod = body_el.addChildElement("EncryptedMethod", "xenc");
	    name = new PrefixedQName(null,"Algorithm",null);
	    if (alg.equals("DES")) encrmethod.addAttribute(name,"http://www.w3.org/2001/04/xmlenc#des-cbc");
	    if (alg.equals("RSA")) encrmethod.addAttribute(name,"http://www.w3.org/2001/04/xmlenc#rsa-ecb");
	    
	    name = new PrefixedQName("http://www.w3.org/2000/09/xmldsig#","KeyInfo","ds");
	    SOAPElement keyinfo = body_el.addChildElement(name);
	    SOAPElement keyname = keyinfo.addChildElement("KeyName","ds");
	    keyname.addTextNode(owner);

	    SOAPElement cypherdata = body_el.addChildElement("CipherData", "xenc");
	    SOAPElement cyphervalue = cypherdata.addChildElement("CipherValue","xenc");
	    cyphervalue.addTextNode(ciphertext); 
	    

	} catch (Exception e) {
	    logger.log(Level.SEVERE,"Unexpected soap body processing fault",e);
	    throw new WSEncryptionException("Unexpected soap body processing fault");}


	// NOTE!!! creating a new message is essational both 
	// here and at the end of a decryption to make things 
	// work with axis and attachements.

	// pull off the attachments

	Iterator attIterator = msg.getAttachments();
	Map attachmentMap = new HashMap();
	List attachments = new ArrayList();
	AttachmentPart aP = null;
	try{
	    while(attIterator.hasNext()) {
		aP = (AttachmentPart) attIterator.next();
		attachmentMap.put(aP.getContentId(),aP.getDataHandler());
		attachments.add(aP);
	    }	
	}catch (Exception e) {}
		    

	// create a new message

	msg = new Message(envelope,false);


	// reinsert the attachments in the new message

	attIterator = attachments.iterator();
	while(attIterator.hasNext()) {
	    aP = (AttachmentPart) attIterator.next();
	    msg.addAttachmentPart(aP);
	}

	return msg;

    }

	




    public SOAPMessage decrypt(SOAPMessage msg, TypeMapping tm, Key key) throws WSEncryptionException {
	
	Name name;
	String cleartext = null;
	byte[] cleartext_bytes = null;
	byte[] ciphertext_bytes = null;
	String ciphertext = null;
	
	SOAPPart sp = msg.getSOAPPart();
	SOAPEnvelope envelope = null;
	SOAPBody body = null;
	Iterator i;

	Security.addProvider(new BouncyCastleProvider());

	org.apache.commons.codec.binary.Base64 codec = new org.apache.commons.codec.binary.Base64();

	

	// remove security header --- no header checks at the moment -- but improve with checks 
	try{
	    envelope = sp.getEnvelope();
	    SOAPHeader header = envelope.getHeader();
	    name = new PrefixedQName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd","Security","wsse");
	    i = header.getChildElements(name);
	    if (i.hasNext()) {
		name = new PrefixedQName("http://www.w3.org/2001/04/xmlenc#","ReferenceList","xenc");
		SOAPHeaderElement header_el = (SOAPHeaderElement) i.next();
		Iterator j = header_el.getChildElements(name);
		if (j.hasNext()) {
		    ((Node)j.next()).detachNode();
		}
		j = header_el.getChildElements();
		if (!(j.hasNext())) ((Node) header_el).detachNode();
	    }

	} catch (Exception e) {
	    logger.log(Level.SEVERE,"Unexpected soap header processing fault",e);
	    throw new WSEncryptionException("Unexpected soap header processing fault");}

	


	// extract ciphertext from the body and decrpt

	try{
	    
	    body = envelope.getBody();
	    envelope.getBody().detachNode();

	    name = new PrefixedQName("http://www.w3.org/2001/04/xmlenc#","EncryptedData","xenc");
	    i = body.getChildElements(name);
	    Iterator j = null;
	    Iterator r = null;
	    String att = null;
	    String alg = null;
	    SOAPElement el,el1,el2,el3;

	    while (i.hasNext()) {
		el = (SOAPElement) i.next();
		name = new PrefixedQName("http://www.w3.org/2001/04/xmlenc#","EncryptedMethod","xenc");
		j = el.getChildElements(name);
		if (j.hasNext()) {
		    name = new PrefixedQName(null,"Algorithm",null);
		    att = ((SOAPElement) j.next()).getAttributeValue(name); 
		    if (att.equals("http://www.w3.org/2001/04/xmlenc#des-cbc"))
			alg = "DES";
		    else if (att.equals("http://www.w3.org/2001/04/xmlenc#rsa-ecb")) 
			alg = "RSA";		  
		}
		name = new PrefixedQName("http://www.w3.org/2000/09/xmldsig#","KeyInfo","ds");
		j = el.getChildElements(name);
		if (j.hasNext()) {
		    el1 = (SOAPElement) j.next();
		    name = new PrefixedQName("http://www.w3.org/2000/09/xmldsig#","KeyName","ds");
		    j = el1.getChildElements(name);
		    el2 = (SOAPElement) j.next();
		    
		}
		name = new PrefixedQName("http://www.w3.org/2001/04/xmlenc#","CipherData","xenc");
		j = el.getChildElements(name);
		while (j.hasNext()) {
		    name = new PrefixedQName("http://www.w3.org/2001/04/xmlenc#","CipherValue","xenc");
		    r = ((SOAPElement) j.next()).getChildElements(name);
		    while (r.hasNext()) {
			ciphertext = ((SOAPElement) r.next()).getValue();



			if (key instanceof SecretKey) {
			    if (!(alg.equals("DES"))) throw new WSEncryptionException("Unsupported encryption algorithm"); 
			    
			    try{
				
				ciphertext_bytes = Base64.decodeBase64(ciphertext.getBytes("UTF-8"));
				
				
				byte[] salt = {(byte)0x8E, 0x12, 0x39, (byte)0x9C,
					       0x07, 0x72, 0x6F, 0x5A};

				IvParameterSpec iv = new IvParameterSpec(salt); 

				
				Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding","BC");
				c.init(Cipher.DECRYPT_MODE,key,iv);

				
				ByteArrayInputStream bIn = new ByteArrayInputStream(ciphertext_bytes);
				CipherInputStream cIn = new CipherInputStream(bIn, c);
				
				ByteArrayOutputStream bOut = new ByteArrayOutputStream();

				byte[] buf = new byte[1024];
				int numRead = 0;
				while ((numRead = cIn.read(buf)) >= 0) {
				    bOut.write(buf,0,numRead);
				}

				bOut.close();
				
				cleartext_bytes = bOut.toByteArray();
								
				cleartext = new String(cleartext_bytes,"UTF-8");




				// DECRYPTION OF ATTACHEMENTS. Attachements are retrived, encrypted and again set
				// to the SOAP message.
				
				Iterator iterator = msg.getAttachments(); 
				AttachmentPart aP;
				InputStream istream;
				byte[] attachment_bytes; 
				byte[] attachment_cleartext;
				int num;
				String type;
			
				while(iterator.hasNext()) {
				    aP = (AttachmentPart) iterator.next();
				    type = (aP.getMimeHeader("encrypted"))[0];
				    
				    try{  
					istream = (InputStream) aP.getContent();
					
					OutputInputStream pOut = new OutputInputStream();
					
					FillCryptotext f = new FillCryptotext(istream,pOut,c);
					((Thread)f).start();

			
					CryptoDataSource cds = new CryptoDataSource(pOut,type);
					javax.activation.DataHandler h = new javax.activation.DataHandler(cds);				  
					aP.setDataHandler(h);

				
				    }catch(Exception e){
					logger.log(Level.SEVERE,"Unexpected symmetric decryption fault while processing attachments",e);
					throw new WSEncryptionException("Unexpected symmetric decryption fault while processing attachments");}
				}

				
			    } catch (Exception e) {
				logger.log(Level.SEVERE,"Unexpected symmetric decryption fault",e);
				e.printStackTrace();
				throw new WSEncryptionException("Unexpected symmetric decryption fault");}
			}

			else if (key instanceof RSAPrivateKey) {
			    if (!(alg.equals("RSA"))) {
				throw new WSEncryptionException("Unsupported decryption algorithm");
			    }
			    
			    try{

				ciphertext_bytes = Base64.decodeBase64(ciphertext.getBytes("UTF-8")); 
				Cipher c = Cipher.getInstance("RSA/ECB/OAEPPadding","BC");
				c.init(Cipher.DECRYPT_MODE,key);

				int inblocksize = c.getBlockSize();
				int outblocksize = c.getOutputSize(inblocksize);	
				int ciphertextsize = ciphertext_bytes.length;
				
				int blocknumber = ciphertextsize/inblocksize;
				
				int ii=0,rr=0;
				byte[] inblock = new byte[inblocksize];
				byte[] outblock = new byte[outblocksize];
				cleartext = new String();
				
				for (ii=0;ii<blocknumber;ii=ii+1) {     	    
				    
				    for (rr=0;rr<inblocksize;rr=rr+1){
					inblock[rr] = ciphertext_bytes[ii*inblocksize + rr];
				    }
				    
				    outblock = c.doFinal(inblock);
				    cleartext = cleartext.concat(new String(outblock, "UTF-8"));
				   
				}
				
				
			    } catch (Exception e) {
				logger.log(Level.SEVERE,"Unexpected private-key decryption fault",e);
				e.printStackTrace();
				throw new WSEncryptionException("Unexpected private-key decryption fault");}
			}
		    }
		}
  	    }
	}catch (Exception e) {
	    logger.log(Level.SEVERE,"The message could not be decrypted",e);
	    System.out.println("The message could not be decrypted");
	    e.printStackTrace();}

	
	//deserialize cleartext string into a SOAPElement 
	
	MessageContext msgContext = new MessageContext(new AxisServer());
	TypeMappingRegistry reg = msgContext.getTypeMappingRegistry();
	if (tm == null) {
	    tm = (TypeMapping) reg.createTypeMapping();
	}
	reg.register(Constants.URI_DEFAULT_SOAP_ENC, tm);

	cleartext = (cleartext.replaceFirst("<?.*?>","")).trim();
	
	cleartext = "<?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv ='http://schemas.xmlsoap.org/soap/envelope/'><soapenv:Body>" + cleartext + "</soapenv:Body></soapenv:Envelope>";
	Reader stringReader = new StringReader(cleartext);
	DeserializationContext context = 
	    new DeserializationContextImpl(new InputSource(stringReader),msgContext,Message.REQUEST);
	
	try{
	    context.parse();
	}catch (Exception e) {new WSEncryptionException("Unexpected cleartext deserialization fault");}

	SOAPEnvelope contents = context.getEnvelope();
	


	//build up a new message with the cleartext as body.

	//pull off the attachments
	Iterator attIterator = msg.getAttachments();
	Map attachmentMap = new HashMap();
	List attachments = new ArrayList();
	AttachmentPart aP = null;
	try{
	    while(attIterator.hasNext()) {
		aP = (AttachmentPart) attIterator.next();
		attachmentMap.put(aP.getContentId(),aP.getDataHandler());
		attachments.add(aP);
	    }	
	}catch (Exception e) {}
		    

	msg = new Message(contents,false);

	// reinsert the attachments in the new message
	attIterator = attachments.iterator();
	while(attIterator.hasNext()) {
	    aP = (AttachmentPart) attIterator.next();
	    msg.addAttachmentPart(aP);
	}
	try{
	    msg.saveChanges();
	}catch(Exception e) {e.printStackTrace();}
	return msg;
    }
 
}
