<commit_before>/***************************************************************************
 *   Copyright (C) by <NAME>                                     *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library General Public License as       *
 *   published by the Free Software Foundation; either version 2 of the    *
 *   License, or (at your option) any later version.                       *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 *                                                                         *
 *   For details about the authors of this software, see the AUTHORS file. *
 ***************************************************************************/

package jolie.net.http;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import jolie.runtime.ByteArray;
import jolie.runtime.Value;

public class MultiPartFormDataParser
{
	private final String boundary;
	private final Value value;
	private final HttpMessage message;
	private final Map< String, PartProperties > partPropertiesMap = new HashMap< String, PartProperties >();

	private static final Pattern parametersSplitPattern = Pattern.compile( ";" );
	private static final Pattern keyValueSplitPattern = Pattern.compile( "=" );

	public class PartProperties {
		private String filename = null;
		private void setFilename( String filename )
		{
			this.filename = filename;
		}
		public String filename()
		{
			return filename;
		}
	}
	
	public MultiPartFormDataParser( HttpMessage message, Value value )
		throws IOException
	{
		final String[] params = parametersSplitPattern.split( message.getProperty( "content-type" ) );
		String b = null;
		try {
			for( String param : params ) {
				param = param.trim();
				if ( param.startsWith( "boundary" ) ) {
					b = "--" + param.split( "=" )[1];
				}
			}
			if ( b == null ) {
				throw new IOException( "Invalid boundary in multipart/form-data http message" );
			}
		} catch( ArrayIndexOutOfBoundsException e ) {
			throw new IOException( "Invalid boundary in multipart/form-data http message" );
		}
		
		this.value = value;
		this.boundary = b;
		this.message = message;
	}

	private PartProperties getPartProperties( String partName )
	{
		PartProperties ret = partPropertiesMap.get( partName );
		if ( ret == null ) {
			ret = new PartProperties();
			partPropertiesMap.put( partName, ret );
		}
		return ret;
	}

	public Collection< Entry< String, PartProperties > > getPartPropertiesSet()
	{
		return partPropertiesMap.entrySet();
	}
	
	private void parsePart( String part, int offset )
		throws IOException
	{
		boolean hasContentType;
		// Split header from content
		String[] hc = part.split( HttpUtils.CRLF + HttpUtils.CRLF, 2 );
		BufferedReader reader =
			new BufferedReader(
			new StringReader( hc[0] ) );
		String line, name = null, filename = null;
		String[] params;

		// Parse part header
		hasContentType = false;
		while( (line=reader.readLine()) != null && !line.isEmpty() ) {
			params = parametersSplitPattern.split( line );
			for( String param : params ) {
				param = param.trim();
				if ( param.startsWith( "name" ) ) {
					try {
						name = keyValueSplitPattern.split( param )[1];
						// Names are surronded by "": cut them.
						name = URLDecoder.decode( name.substring( 1, name.length() - 1 ), HttpUtils.URL_DECODER_ENC );
					} catch( ArrayIndexOutOfBoundsException e ) {
						throw new IOException( "Invalid name specified in multipart form data element" );
					}
				} else if ( param.startsWith( "filename" ) ) {
					try {
						filename = keyValueSplitPattern.split( param )[1];
						// Filenames are surronded by quotes "": cut them.<commit_msg>MultiPartFormDataParser - some more split() fixes (similar to bug #52)<commit_after>/***************************************************************************
 *   Copyright (C) by <NAME>                                     *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library General Public License as       *
 *   published by the Free Software Foundation; either version 2 of the    *
 *   License, or (at your option) any later version.                       *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 *                                                                         *
 *   For details about the authors of this software, see the AUTHORS file. *
 ***************************************************************************/

package jolie.net.http;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import jolie.runtime.ByteArray;
import jolie.runtime.Value;

public class MultiPartFormDataParser
{
	private final String boundary;
	private final Value value;
	private final HttpMessage message;
	private final Map< String, PartProperties > partPropertiesMap = new HashMap< String, PartProperties >();

	private static final Pattern parametersSplitPattern = Pattern.compile( ";" );
	private static final Pattern keyValueSplitPattern = Pattern.compile( "=" );

	public class PartProperties {
		private String filename = null;
		private void setFilename( String filename )
		{
			this.filename = filename;
		}
		public String filename()
		{
			return filename;
		}
	}
	
	public MultiPartFormDataParser( HttpMessage message, Value value )
		throws IOException
	{
		final String[] params = parametersSplitPattern.split( message.getProperty( "content-type" ) );
		String b = null;
		try {
			for( String param : params ) {
				param = param.trim();
				if ( param.startsWith( "boundary" ) ) {
					b = "--" + keyValueSplitPattern.split( param, 2 )[1];
				}
			}
			if ( b == null ) {
				throw new IOException( "Invalid boundary in multipart/form-data http message" );
			}
		} catch( ArrayIndexOutOfBoundsException e ) {
			throw new IOException( "Invalid boundary in multipart/form-data http message" );
		}
		
		this.value = value;
		this.boundary = b;
		this.message = message;
	}

	private PartProperties getPartProperties( String partName )
	{
		PartProperties ret = partPropertiesMap.get( partName );
		if ( ret == null ) {
			ret = new PartProperties();
			partPropertiesMap.put( partName, ret );
		}
		return ret;
	}

	public Collection< Entry< String, PartProperties > > getPartPropertiesSet()
	{
		return partPropertiesMap.entrySet();
	}
	
	private void parsePart( String part, int offset )
		throws IOException
	{
		boolean hasContentType;
		// Split header from content
		String[] hc = part.split( HttpUtils.CRLF + HttpUtils.CRLF, 2 );
		BufferedReader reader =
			new BufferedReader(
			new StringReader( hc[0] ) );
		String line, name = null, filename = null;
		String[] params;

		// Parse part header
		hasContentType = false;
		while( (line=reader.readLine()) != null && !line.isEmpty() ) {
			params = parametersSplitPattern.split( line );
			for( String param : params ) {
				param = param.trim();
				if ( param.startsWith( "name" ) ) {
					try {
						name = keyValueSplitPattern.split( param, 2 )[1];
						// Names are surronded by "": cut them.
						name = URLDecoder.decode( name.substring( 1, name.length() - 1 ), HttpUtils.URL_DECODER_ENC );
					} catch( ArrayIndexOutOfBoundsException e ) {
						throw new IOException( "Invalid name specified in multipart form data element" );
					}
				} else if ( param.startsWith( "filename" ) ) {
					try {
						filename = keyValueSplitPattern.split( param, 2 )[1];
						// Filenames are surronded by quotes "": cut them.
{'fraction_non_alphanumeric': 0.1205324389476994, 'fraction_numerical': 0.005135730007336757, 'mean_word_length': 2.402995720399429, 'pattern_counts': {'":': 4, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 28, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '936669', 'n_tokens_mistral': 2761, 'n_tokens_neox': 2429, 'n_words': 825}