All Downloads are FREE. Search and download functionalities are using the official Maven repository.

test.unit.gov.nist.javax.sip.multipartmime.MultipartMimeParserTest Maven / Gradle / Ivy

package test.unit.gov.nist.javax.sip.multipartmime;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;

import javax.sip.header.ContentTypeHeader;
import javax.sip.message.Request;

import gov.nist.javax.sip.header.ContentType;
import gov.nist.javax.sip.header.HeaderFactoryExt;
import gov.nist.javax.sip.header.HeaderFactoryImpl;
import gov.nist.javax.sip.header.SIPHeader;
import gov.nist.javax.sip.message.Content;
import gov.nist.javax.sip.message.MessageExt;
import gov.nist.javax.sip.message.MessageFactoryExt;
import gov.nist.javax.sip.message.MessageFactoryImpl;
import gov.nist.javax.sip.message.MultipartMimeContent;
import gov.nist.javax.sip.message.SIPRequest;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;

import javax.sip.header.ContentTypeHeader;
import javax.sip.message.Request;

import junit.framework.TestCase;

public class MultipartMimeParserTest extends TestCase {
  private static String messageSting1 = "INVITE sip:5201;[email protected];user=phone SIP/2.0\r\n"
                                        + "Via: SIP/2.0/TCP 47.11.74.26:5060;branch=z9hG4bKc51760e4d76173c00cd32f19.1;rport=5060\r\n"
                                        + "Via: SIP/2.0/TCP 47.11.27.84:5060;branch=z9hG4bK-34ec-cebbcb-3278c0e6;received=47.11.27.84\r\n"
                                        + "Record-Route: \r\n"
                                        + "From: \"Nirav Sheth2050\" ;tag=b5107990-541b0b2f-13c4-40030-34ec-728605b1-34ec\r\n"
                                        + "To: \r\n"
                                        + "Call-ID: b4eda330-541b0b2f-13c4-40030-34ec-55f3f5db-34ec\r\n"
                                        + "CSeq: 1 INVITE\r\n"
                                        + "Contact: \r\n"
                                        + "Max-Forwards: 69\r\n"
                                        + "Supported: 100rel,x-nortel-sipvc,replaces,timer\r\n"
                                        + "User-Agent: Nortel CS1000 SIP GW release_6.0 version_ssLinux-6.00.18\r\n"
                                        + "P-Asserted-Identity: \"Nirav Sheth2050\" \r\n"
                                        + "Privacy: none\r\n"
                                        + "History-info: ;index=1\r\n"
                                        + "X-nt-corr-id: 000000220e182d1508@001bbafd3d0f-2f0b1b42\r\n" + "Min-SE: 0\r\n"
                                        + "Allow: INVITE,ACK,BYE,REGISTER,REFER,NOTIFY,CANCEL,PRACK,OPTIONS,INFO,SUBSCRIBE,UPDATE\r\n"
                                        + "Content-Length: 0\r\n\r\n";
  private static String contentType1 = "Content-Type: multipart/mixed;boundary=unique-boundary-1\r\n";
  private static String contentString1 = "--unique-boundary-1\r\n"
                                         + "Content-Type: application/sdp\r\n\r\n"
                                         + "v=0\r\n"
                                         + "o=- 1 1 IN IP4 47.11.27.84\r\n"
                                         + "s=-\r\n"
                                         + "t=0 0\r\n"
                                         + "m=audio 5200 RTP/AVP 0 8 18 101 111\r\n"
                                         + "c=IN IP4 47.9.17.80\r\n"
                                         + "a=tcap:1 RTP/SAVP\r\n"
                                         + "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:+v5UQZeJ2ecQbS/yNQJgnpqHwu2utWwAdpaWh7Ke|2^31|543245432:4\r\n"
                                         + "a=crypto:2 AES_CM_128_HMAC_SHA1_80 inline:+v5UQZeJ2ecQbS/yNQJgnpqHwu2utWwAdpaWh7Ke|2^31\r\n"
                                         + "a=pcfg:1 t=1\r\n" + "a=fmtp:18 annexb=no\r\n" + "a=rtpmap:101 telephone-event/8000\r\n"
                                         + "a=fmtp:101 0-15\r\n" + "a=rtpmap:111 X-nt-inforeq/8000\r\n" + "a=ptime:20\r\n"
                                         + "a=sendrecv\r\n\r\n" + "--unique-boundary-1\r\n"
                                         + "Content-Type: application/x-nt-mcdn-frag-hex;version=ssLinux-6.00.18;base=x2611\r\n"
                                         + "Content-Disposition: signal;handling=optional\r\n\r\n" + "0500c001\r\n"
                                         + "0107130081900000a200\r\n" + "09090f00e9a0830001004000\r\n"
                                         + "131e070011fd1800a1160201010201a1300e8102010582010184020000850104\r\n"
                                         + "1315070011fa0f00a10d02010102020100cc040000748800\r\n" + "1e0403008183\r\n"
                                         + "460e01000a0001000100010000000000\r\n" + "--unique-boundary-1\r\n"
                                         + "Content-Type: application/x-nt-epid-frag-hex;version=ssLinux-6.00.18;base=x2611\r\n"
                                         + "Content-Disposition: signal;handling=optional\r\n\r\n" + "011201\r\n" + "00:1b:ba:fd:3d:0f\r\n"
                                         + "--unique-boundary-1\r\n";
  
  private static final String usnistgovissue16 = 
			"--unique-boundary-1\n\r" +
			"Content-Type: application/sdp\n\r" +
			"\n\r" +
			"v=0\n\r" +
			"o=- 999999 999999 IN IP4 99.99.99.99\n\r" +
			"s=-\n\r" +
			"c=IN IP4 99.99.99.99\n\r" +
			"t=0 0\n\r" +
			"m=audio 99999 RTP/AVP 0 101\n\r" +
			"a=rtpmap:0 PCMU/8000\n\r" +
			"a=rtpmap:101 telephone-event/8000\n\r" +
			"a=fmtp:101 0-15\n\r" +
			"a=maxptime:20\n\r" +
			"a=label:3199936\n\r" +
			"a=inactive\n\r" +
			"m=audio 0 RTP/AVP 0 101\n\r" +
			"a=rtpmap:0 PCMU/8000\n\r" +
			"a=rtpmap:101 telephone-event/8000\n\r" +
			"a=fmtp:101 0-15\n\r" +
			"a=maxptime:20\n\r" +
			"a=inactive\n\r" +
			"a=label:3199937\n\r" +
			"\n\r" +
			"--unique-boundary-1\n\r" +
			"Content-Type: application/rs-metadata+xml\n\r" +
			"Content-Disposition: recording-session\n\r" +
			"\n\r" +
			"\n" +
			"\n" +
			"\tcomplete\n" +
			"\t\n" +
			"\t\t2016-10-12T12:07:18\n" +
			"\t\t\n" +
			"\t\t\t00FA08XXXXXXXXXXXXXXXX;encoding=hex\n" +
			"\t\t\ttrue\n" +
			"\t\t\n" +
			"\t\n" +
			"\t\n" +
			"\t\t\n" +
			"\t\t\t"XXXXXXXXXXXXXXX"\n" +
			"\t\t\n" +
			"\t\tGjCvWYoEQh9zN9TsyCVl/w==\n" +
			"\t\t2016-10-12T12:07:18\n" +
			"\t\t\n" +
			"\t\t\ttrue\n" +
			"\t\t\tsip:[email protected]:5060\n" +
			"\t\t\toutsideXO\n" +
			"\t\t\t\n" +
			"\t\t\t\t"XXXXXXXXXXXXXXX" <sip:[email protected]:5060;pstn-params=9999999999>;tag=xxxxxxxxxx\n" +
			"\t\t\t\n" +
			"\t\t\t\n" +
			"\t\t\t\t<sip:[email protected]:5060>\n" +
			"\t\t\t\n" +
			"\t\t\t\n" +
			"\t\t\t\t[email protected]\n" +
			"\t\t\t\n" +
			"\t\t\n" +
			"\t\n" +
			"\t\n" +
			"\t\t\n" +
			"\t\t\t9999999999\n" +
			"\t\t\n" +
			"\t\t2016-10-12T12:07:18\n" +
			"\t\t\n" +
			"\t\t\tfalse\n" +
			"\t\t\n" +
			"\t\n" +
			"\t\n" +
			"\t\t\n" +
			"\t\tseparate\n" +
			"\t\t2016-10-12T12:07:18\n" +
			"\t\n" +
			"\r\n" +
			"--unique-boundary-1--\r\n";

  private static String contentString2 = 
		  "--boundary1\n"
		  + "Content-Type: application/sdp\n"
		  + "\n"
		  + "v=0\n"
		  + "o=IWSPM 2266426 2266426 IN IP4 10.92.9.164\n"
		  + "s=-\n"
		  + "c=IN IP4 10.92.9.164\n"
		  + "t=0 0\n"
		  + "m=audio 31956 RTP/AVP 0 8 18 101\n"
		  + "a=ptime:20\n"
		  + "a=rtpmap:101 telephone-event/8000\n"
		  + "a=fmtp:101 0-15\n"
		  + "\n"
		  + "--boundary1\n"
		  + "Content-Type: application/pidf+xml\n"
		  + "Content-ID: [email protected]\n"
		  + "\n"
		  + "\n"
		  + "\n"
										  + "\n"
										  + "2007-07-09T14:00:00Z\n"
		   + "\n"
		    + "\n"
		    + "\r\n"
		  	+ "\n"
		  	  + "\n"
		  		+ "\n"
		  		+ "33.001111 -96.68142\n"
		  		+ "\n"
		  	   + "\n"
		  	+ "\n"
			+ "\n"
		  	+ "\n"
		  	  + "no\n"
		  	  + "2007-07-27T18:00:00Z\n"
		  	+ "\n"
		  	+ "DHCP\n"
		  	+ "www.example.com\n"
		    + "\n"
		   + "\n"
		  + "\n"
		  + "\n"
		  + "--boundary1--\n";

  
  private static String simpleContentWithEmptyLine = "\n"
    + "v=0\n"
    + "o=IWSPM 2266426 2266426 IN IP4 10.92.9.164\n"
    + "s=-\n"
    + "c=IN IP4 10.92.9.164\n"
    + "\n"
    + "t=0 0\n"
    + "m=audio 31956 RTP/AVP 0 8 18 101\n"
    + "a=ptime:20\n"
    + "a=rtpmap:101 telephone-event/8000\n"
    + "a=fmtp:101 0-15\n"
    + "\n";
  
  private static String multipartContentWithEmptyLine = "\n"
    + "--boundary1\n"
    + "Content-Type: message/sip\n"
    + "\n"
    + "INVITE sip:[email protected] SIP/2.0\n"
    + "Via: SIP/2.0/UDP pc33.atlanta.com;branch=z9hG4bKnashds8\n"
    + "To: Bob \n"
    + "From: Alice ;tag=1928301774\n"
    + "Call-ID: a84b4c76e66710\n"
    + "CSeq: 314159 INVITE\n"
    + "Max-Forwards: 70\n"
    + "Date: Thu, 21 Feb 2002 13:02:03 GMT\n"
    + "Contact: \n"
    + "Content-Type: application/sdp\n"
    + "Content-Length: 147\n"
    + "\n"
    + "v=0\n"
    + "o=UserA 2890844526 2890844526 IN IP4 here.com\n"
    + "s=Session SDP\n"
    + "c=IN IP4 pc33.atlanta.com\n"
    + "t=0 0\n"
    + "m=audio 49172 RTP/AVP 0\n"
    + "a=rtpmap:0 PCMU/8000\n"
    + "\n"
    + "--boundary1\n"
    + "Content-Type: application/pkcs7-signature; name=smime.p7s\n"
    + "Content-Transfer-Encoding: base64\n"
    + "Content-Disposition: attachment; filename=smime.p7s; handling=required\n"
    + "\n"
    + "ghyHhHUujhJhjH77n8HHGTrfvbnj756tbB9HG4VQpfyF467GhIGfHfYT6\n"
    + "4VQpfyF467GhIGfHfYT6jH77n8HHGghyHhHUujhJh756tbB9HGTrfvbnj\n"
    + "n8HHGTrfvhJhjH776tbB9HG4VQbnj7567GhIGfHfYT6ghyHhHUujpfyF4\n"
    + "7GhIGfHfYT64VQbnj756\n"
    + "\n"
    + "--boundary1--\n";

  
  private static String messageString = "INVITE sip:[email protected] SIP/2.0\r\n"
                                        + "Via: SIP/2.0/UDP pc33.server1.com;branch=z9hG4bK776asdhds\r\n" + "Max-Forwards: 70\r\n"
                                        + "To: user2 \r\n"
                                        + "From: user1 ;tag=1928301774\r\n"
                                        + "Call-ID: [email protected]\r\n" + "CSeq: 314159 INVITE\r\n"
                                        + "Contact: \r\n" + "Content-Length: 0\r\n\r\n";

  String type[] = { "application", "applicaiton" };
  String subtype[] = { "sdp", "p25issi" };
  String content[] = {
                      "v=0\r\n" + "o=ali 1122334455 1122334466 IN IP4 rams.example.com\r\n" + "s=Rapid Acquisition Examples\r\n"
                        + "t=0 0\r\n" + "a=group:FID 1 2\r\n" + "a=rtcp-unicast:rsi\r\n" + "m=video 40000 RTP/AVPF 96\r\n"
                        + "c=IN IP4 224.1.1.1/255\r\n" + "a=source-filter: incl IN IP4 224.1.1.1 192.0.2.2\r\n" + "a=recvonly\r\n"
                        + "a=rtpmap:96 MP2T/90000\r\n" + "m=video 40002 RTP/AVPF 97\r\n"
                        + "i=Unicast Retransmission Stream #1 (Ret. Support Only)\r\n" + "c=IN IP4 192.0.2.1\r\n" + "a=recvonly\r\n"
                        + "a=rtpmap:97 rtx/90000\r\n" + "a=rtcp:40003\r\n" + "a=fmtp:97 apt=96\r\n",

                      "g-access:1\r\n" + "g-agroup:0B4561A27271\r\n" + "g-pri:2\r\n" + "g-ecap:1\r\n" + "g-eprempt:0\r\n"
                        + "g-rfhangt:0\r\n" + "g-ccsetupT:0\r\n" + "g-intmode:0\r\n" + "g-sec:1\r\n" + "g-ic:0\r\n" + "g-icsecstart:0\r\n" };

  private static MessageFactoryExt messageFactory = new MessageFactoryImpl();
  private static HeaderFactoryExt headerFactory = new HeaderFactoryImpl();

  @Override
  public void setUp() throws Exception {

  }

  public void testCreateMultipartMimeContent() throws Exception {
    MessageExt sipMessage = (MessageExt) messageFactory.createRequest(messageString);
    ContentTypeHeader cth = headerFactory.createContentTypeHeader("multipart", "alternative");
    cth.setParameter("boundary", "myboundary");
    MultipartMimeContent mmc = messageFactory.createMultipartMimeContent(cth, type, subtype, content);
    Iterator contentIterator = mmc.getContents();

    int i = 0;
    while (contentIterator.hasNext()) {
      Content contentImpl = contentIterator.next();
      assertEquals("Content must match", content[i], contentImpl.getContent());
      assertEquals("Content Type match", type[i], contentImpl.getContentTypeHeader().getContentType());
      assertEquals("Content subtype match", subtype[i], contentImpl.getContentTypeHeader().getContentSubType());
      i++;
    }

    String mmcContentString = mmc.toString();
    sipMessage.setContent(mmcContentString, cth);
    MultipartMimeContent mmc1 = sipMessage.getMultipartMimeContent();
    contentIterator = mmc1.getContents();

    i = 0;
    while (contentIterator.hasNext()) {
      Content contentImpl = contentIterator.next();
      assertEquals("Content must match", content[i], contentImpl.getContent().toString());
      assertEquals("Content Type match", type[i], contentImpl.getContentTypeHeader().getContentType());
      assertEquals("Content subtype match", subtype[i], contentImpl.getContentTypeHeader().getContentSubType());
      i++;
    }

    MessageExt message1 = (MessageExt) messageFactory.createRequest(messageSting1);
    ContentTypeHeader cth1 = (ContentTypeHeader) ((HeaderFactoryExt) headerFactory).createHeader(contentType1);
    message1.setContent(contentString1, cth1);

    System.out.println("SIP Message after adding content " + message1);

    MultipartMimeContent mmc2 = message1.getMultipartMimeContent();

    Iterator contents = mmc2.getContents();
    while (contents.hasNext()) {
      Content content = contents.next();
      System.out.println("contentTypeHeader = " + content.getContentTypeHeader());
      System.out.println("content = " + content.getContent());
    }

    Request request2 = messageFactory.createRequest(message1.toString());

    MultipartMimeContent mmc3 = ((MessageExt) request2).getMultipartMimeContent();

    Iterator contents2 = mmc3.getContents();

    contents = mmc2.getContents();
    assertTrue("number of fragments dont match", mmc2.getContentCount() == mmc3.getContentCount());
    while (contents2.hasNext()) {
      Content c1 = contents.next();
      Content c2 = contents2.next();
      assertTrue("contents must match", c1.getContent().equals(c2.getContent()));

    }

    System.out.println("After " + request2);

  }

  public void testMultiPartMimeMarshallingAndUnMarshallingWithExtraHeaders() throws Exception {
    SIPRequest request = new SIPRequest();
//    InputStream in = getClass().getClassLoader().getResourceAsStream("test/unit/gov/nist/javax/sip/multipartmime/multipart-body.txt");
//    byte[] content = toByteArray(in);
    byte[] content = contentString2.getBytes("UTF-8");
    ContentType contentType = new ContentType("multipart", "mixed");
    contentType.setParameter("boundary", "boundary1");
    
    request.setContent(content, contentType);
    MultipartMimeContent multipartMimeContent = request.getMultipartMimeContent();
    checkMultiPart(multipartMimeContent);

    // let's now marshall back the body and reparse it to check consistency
    String bodyContent = multipartMimeContent.toString();
    request.setContent(bodyContent, contentType);
    MultipartMimeContent multipartMimeContent2 = request.getMultipartMimeContent();
    checkMultiPart(multipartMimeContent2);
  }
  
  public void testMultiPartMimeMarshallingAndUnMarshallingWithExtraHeadersAndSpaces() throws Exception {
    SIPRequest request = new SIPRequest();
    byte[] content = multipartContentWithEmptyLine.getBytes("UTF-8");
    ContentType contentType = new ContentType("multipart", "mixed");
    contentType.setParameter("boundary", "boundary1");
    
    request.setContent(content, contentType);
    MultipartMimeContent multipartMimeContent = request.getMultipartMimeContent();
    checkMultiPartWithSpaces(multipartMimeContent);
    
    // let's now marshall back the body and reparse it to check consistency
    String bodyContent = multipartMimeContent.toString();
    request.setContent(bodyContent, contentType);
    MultipartMimeContent multipartMimeContent2 = request.getMultipartMimeContent();
    checkMultiPartWithSpaces(multipartMimeContent2);
  }
  
  public void testMultiParUsnistgovtIssue16() throws Exception {
	    SIPRequest request = new SIPRequest();
	    byte[] content = usnistgovissue16.getBytes("UTF-8");
	    ContentType contentType = new ContentType("multipart", "mixed");
	    contentType.setParameter("boundary", "unique-boundary-1");
	    
	    request.setContent(content, contentType);
	    MultipartMimeContent multipartMimeContent = request.getMultipartMimeContent();
	    Iterator partContentIterator = multipartMimeContent.getContents();
	    Content part1 = partContentIterator.next();
	    Content part2 = partContentIterator.next();
	    assertEquals("application/rs-metadata+xml", ((ContentType) part2.getContentTypeHeader()).getValue());
	  }
  
  public void testMultiPartMimeMarshallingAndUnMarshallingWithANonMultiPartBodyWithAnEmptyLine() throws Exception {
    SIPRequest request = new SIPRequest();
    byte[] content = simpleContentWithEmptyLine.getBytes("UTF-8");
    ContentType contentType = new ContentType("application", "sdp");
    request.setContent(content, contentType);
    MultipartMimeContent multipartMimeContent = request.getMultipartMimeContent();
    checkSimpleBody(multipartMimeContent);
    
    // let's now marshall back the body and reparse it to check consistency
    // we just want the content, not the boundaries (which are null)
    String bodyContent = multipartMimeContent.getContents().next().getContent().toString();
    request.setContent(bodyContent, contentType);
    MultipartMimeContent multipartMimeContent2 = request.getMultipartMimeContent();
    checkSimpleBody(multipartMimeContent2);
  }

  private void checkMultiPart(MultipartMimeContent multipartMimeContent) {
    Iterator partContentIterator = multipartMimeContent.getContents();
    Content sdpPart = partContentIterator.next();
    Content pidfPart = partContentIterator.next();

    assertEquals("application/sdp", ((ContentType) sdpPart.getContentTypeHeader()).getValue());
    assertFalse(sdpPart.getExtensionHeaders().hasNext());

    assertEquals("application/pidf+xml", ((ContentType) pidfPart.getContentTypeHeader()).getValue());
    assertTrue(pidfPart.getExtensionHeaders().hasNext());
    assertNotNull(pidfPart.getContent());
    SIPHeader extensionHeader = (SIPHeader) pidfPart.getExtensionHeaders().next();
    assertEquals("Content-ID", extensionHeader.getName());
    assertEquals("[email protected]", extensionHeader.getValue());
    assertNotNull(sdpPart.getContent());
  }

  
  private void checkMultiPartWithSpaces(MultipartMimeContent multipartMimeContent) {
    Iterator partContentIterator = multipartMimeContent.getContents();
    Content part1 = partContentIterator.next();
    Content part2 = partContentIterator.next();

    assertEquals("message/sip", ((ContentType) part1.getContentTypeHeader()).getValue());
    assertFalse(part1.getExtensionHeaders().hasNext());
    assertNotNull(part1.getContent());

    assertEquals("application/pkcs7-signature;name=smime.p7s", ((ContentType) part2.getContentTypeHeader()).getValue());
    assertTrue(part2.getExtensionHeaders().hasNext());
    assertEquals("ghyHhHUujhJhjH77n8HHGTrfvbnj756tbB9HG4VQpfyF467GhIGfHfYT6\n"
                 + "4VQpfyF467GhIGfHfYT6jH77n8HHGghyHhHUujhJh756tbB9HGTrfvbnj\n"
                 + "n8HHGTrfvhJhjH776tbB9HG4VQbnj7567GhIGfHfYT6ghyHhHUujpfyF4\n"
                 + "7GhIGfHfYT64VQbnj756\n", part2.getContent());
    
  }
  

  private void checkSimpleBody(MultipartMimeContent multipartMimeContent) {
    Iterator partContentIterator = multipartMimeContent.getContents();
    Content sdpPart = partContentIterator.next();
    
    assertEquals("application/sdp", ((ContentType) sdpPart.getContentTypeHeader()).getValue());
    assertFalse(sdpPart.getExtensionHeaders().hasNext());
    
    assertNotNull(sdpPart.getContent());
    assertFalse(partContentIterator.hasNext());
  }
  
  private byte[] toByteArray(InputStream input) throws IOException {
    ByteArrayOutputStream output = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int n = 0;
    while (-1 != (n = input.read(buffer))) {
      output.write(buffer, 0, n);
    }
    return output.toByteArray();
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy