<commit_before>//
//  MimeReader.swift
//  PerfectLib
//
//  Created by <NAME> on 7/6/15.
//	Copyright (C) 2015 PerfectlySoft, Inc.
//
//===----------------------------------------------------------------------===//
//
// This source file is part of the Perfect.org open source project
//
// Copyright (c) 2015 - 2016 PerfectlySoft Inc. and the Perfect project authors
// Licensed under Apache License v2.0
//
// See http://perfect.org/licensing.html for license information
//
//===----------------------------------------------------------------------===//
//

#if os(Linux)
	import Foundation
	import LinuxBridge
	let S_IRUSR = __S_IREAD
	let S_IRGRP	= (S_IRUSR >> 3)
	let S_IWGRP	= (SwiftGlibc.S_IWUSR >> 3)
	let S_IROTH = (S_IRGRP >> 3)
	let S_IWOTH = (S_IWGRP >> 3)
#else
	import Darwin
#endif
import PerfectLib

enum MimeReadState {
	case stateNone
	case stateBoundary // next thing to be read will be a boundry
	case stateHeader // read header lines until data starts
	case stateFieldValue // read a simple value; name has already been set
	case stateFile // read file data until boundry
	case stateDone
}

let kMultiPartForm = "multipart/form-data"
let kBoundary = "boundary"

let kContentDisposition = "Content-Disposition"
let kContentType = "Content-Type"

let kPerfectTempPrefix = "perfect_upload_"

let mime_cr: UInt8 = 13
let mime_lf: UInt8 = 10
let mime_dash: UInt8 = 45

/// This class is responsible for reading multi-part POST form data, including handling file uploads.
/// Data can be given for parsing in little bits at a time by calling the `addTobuffer` function.
/// Any file uploads which are encountered will be written to the temporary directory indicated when the `MimeReader` is created.
/// Temporary files will be deleted when this object is deinitialized.
public final class MimeReader {
	
	/// Array of BodySpecs representing each part that was parsed.
	public var bodySpecs = [BodySpec]()
	
	var (multi, gotFile) = (false, false)
	var buffer = [UInt8]()
	let tempDirectory: String
	var state: MimeReadState = .stateNone
	
	/// The boundary identifier.
	public var boundary = ""
	
	/// This class represents a single part of a multi-part POST submission
	public class BodySpec {
		/// The name of the form field.
		public var fieldName = ""
		/// The value for the form field.
		/// Having a fieldValue and a file are mutually exclusive.
		public var fieldValue = ""
		var fieldValueTempBytes: [UInt8]?
		/// The content-type for the form part.
		public var contentType = ""
		/// The client-side file name as submitted by the form.
		public var fileName = ""
		/// The size of the file which was submitted.
		public var fileSize = 0
		/// The name of the temporary file which stores the file upload on the server-side.
		public var tmpFileName = ""
		/// The File object for the local temporary file.
		public var file: File?
		
		init() {
			
		}
		
		/// Clean up the BodySpec, possibly closing and deleting any associated temporary file.
		public func cleanup() {
			if let f = self.file {
				if f.exists {
					f.delete()
				}
				self.file = nil
			}
		}
		
		deinit {
			self.cleanup()
		}
	}
	
	/// Initialize given a Content-type header line.
	/// - parameter contentType: The Content-type header line.
	/// - parameter tempDir: The path to the directory in which to store temporary files. Defaults to "/tmp/".
	public init(_ contentType: String, tempDir: String = "/tmp/") {
		self.tempDirectory = tempDir
		if contentType.hasPrefix(kMultiPartForm) {
			self.multi = true
			if let range = contentType.range(of: kBoundary) {
				
				let startIndex = contentType.index(range.lowerBound, offsetBy: kBoundary.count+1)
				let endIndex = contentType.endIndex
				
				let boundaryString = String(contentType[startIndex..<endIndex]) ?? ""
				self.boundary.append("--")
				self.boundary.append(boundaryString)
				self.state = .stateBoundary
			}
		}
	}
	
	func openTempFile(spec spc: BodySpec) {<commit_msg>Update MimeReader.swift<commit_after>//
//  MimeReader.swift
//  PerfectLib
//
//  Created by <NAME> on 7/6/15.
//	Copyright (C) 2015 PerfectlySoft, Inc.
//
//===----------------------------------------------------------------------===//
//
// This source file is part of the Perfect.org open source project
//
// Copyright (c) 2015 - 2016 PerfectlySoft Inc. and the Perfect project authors
// Licensed under Apache License v2.0
//
// See http://perfect.org/licensing.html for license information
//
//===----------------------------------------------------------------------===//
//

#if os(Linux)
	import Foundation
	import LinuxBridge
	let S_IRUSR = __S_IREAD
	let S_IRGRP	= (S_IRUSR >> 3)
	let S_IWGRP	= (SwiftGlibc.S_IWUSR >> 3)
	let S_IROTH = (S_IRGRP >> 3)
	let S_IWOTH = (S_IWGRP >> 3)
#else
	import Darwin
#endif
import PerfectLib

enum MimeReadState {
	case stateNone
	case stateBoundary // next thing to be read will be a boundry
	case stateHeader // read header lines until data starts
	case stateFieldValue // read a simple value; name has already been set
	case stateFile // read file data until boundry
	case stateDone
}

let kMultiPartForm = "multipart/form-data"
let kBoundary = "boundary"

let kContentDisposition = "Content-Disposition"
let kContentType = "Content-Type"

let kPerfectTempPrefix = "perfect_upload_"

let mime_cr: UInt8 = 13
let mime_lf: UInt8 = 10
let mime_dash: UInt8 = 45

/// This class is responsible for reading multi-part POST form data, including handling file uploads.
/// Data can be given for parsing in little bits at a time by calling the `addTobuffer` function.
/// Any file uploads which are encountered will be written to the temporary directory indicated when the `MimeReader` is created.
/// Temporary files will be deleted when this object is deinitialized.
public final class MimeReader {
	
	/// Array of BodySpecs representing each part that was parsed.
	public var bodySpecs = [BodySpec]()
	
	var (multi, gotFile) = (false, false)
	var buffer = [UInt8]()
	let tempDirectory: String
	var state: MimeReadState = .stateNone
	
	/// The boundary identifier.
	public var boundary = ""
	
	/// This class represents a single part of a multi-part POST submission
	public class BodySpec {
		/// The name of the form field.
		public var fieldName = ""
		/// The value for the form field.
		/// Having a fieldValue and a file are mutually exclusive.
		public var fieldValue = ""
		var fieldValueTempBytes: [UInt8]?
		/// The content-type for the form part.
		public var contentType = ""
		/// The client-side file name as submitted by the form.
		public var fileName = ""
		/// The size of the file which was submitted.
		public var fileSize = 0
		/// The name of the temporary file which stores the file upload on the server-side.
		public var tmpFileName = ""
		/// The File object for the local temporary file.
		public var file: File?
		
		init() {
			
		}
		
		/// Clean up the BodySpec, possibly closing and deleting any associated temporary file.
		public func cleanup() {
			if let f = self.file {
				if f.exists {
					f.delete()
				}
				self.file = nil
			}
		}
		
		deinit {
			self.cleanup()
		}
	}
	
	/// Initialize given a Content-type header line.
	/// - parameter contentType: The Content-type header line.
	/// - parameter tempDir: The path to the directory in which to store temporary files. Defaults to "/tmp/".
	public init(_ contentType: String, tempDir: String = "/tmp/") {
		self.tempDirectory = tempDir
		if contentType.hasPrefix(kMultiPartForm) {
			self.multi = true
			if let range = contentType.range(of: kBoundary) {
				
				let startIndex = contentType.index(range.lowerBound, offsetBy: kBoundary.count+1)
				let endIndex = contentType.endIndex
				
				let boundaryString = String(contentType[startIndex..<endIndex])
				self.boundary.append("--")
				self.boundary.append(boundaryString)
				self.state = .stateBoundary
			}
		}
	}
	
	func openTempFile(spec spc: BodySpec) {
{'fraction_non_alphanumeric': 0.13141917530989122, 'fraction_numerical': 0.00885403491019479, 'mean_word_length': 2.73147711184521, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '653247', 'n_tokens_mistral': 2595, 'n_tokens_neox': 2295, 'n_words': 885}