0001    import Foundation
0002    import Echo
0003    import Vaquita
0004    
0005    #if os(Linux)
0006        import Glibc
0007    #else
0008        import Darwin
0009    #endif
0010    
0011    public class Multiparser
Multiparser.swift:233
            if value > Multiparser.CR {
Multiparser.swift:236
            if value == Multiparser.NL {
Multiparser.swift:264
                if body.last == Multiparser.NL {
Multiparser.swift:268
                    if body.last == Multiparser.CR {
: Middleware { 0012 0013 let multipartFormIdentifier = "multipart/form-data" 0014 let boundaryIdentifier = "boundary" 0015 0016 let directory
Multiparser.swift:24
            self.directory = directory
Multiparser.swift:29
            self.directory = NSTemporaryDirectory()
: String 0017 0018 public init(directory: String? = nil) { 0019 #if os(Linux) 0020 srand(UInt32(time(nil))) 0021 #endif 0022 0023 if let directory = directory { 0024 self.directory = directory 0025 } else { 0026 #if os(Linux) 0027 self.directory = "/var/tmp/" 0028 #else 0029 self.directory = NSTemporaryDirectory() 0030 #endif 0031 } 0032 } 0033 0034 0035 func writeData(data: [UInt8], toPath path: String) throws { 0036 let raw = NSData(bytesNoCopy: UnsafeMutablePointer<Void>(data), 0037 length: data.count * sizeof(UInt8), freeWhenDone: false) 0038 0039 try raw.writeToFile(path, options: .DataWritingAtomic) 0040 } 0041 0042 public func handle(request: Request, response: Response, next: (() -> ())) { 0043 0044 guard let contentTypeHeader = request.headers["content-type"] else { 0045 next() 0046 return 0047 } 0048 0049 let contentTypeHeaderTokens = contentTypeHeader.split(";").map { $0.trim() } 0050 guard let contentType = contentTypeHeaderTokens.first where contentType == "multipart/form-data" else { 0051 next() 0052 return 0053 } 0054 0055 var boundary: String? = nil 0056 0057 for token in contentTypeHeaderTokens { 0058 0059 let tokens = token.split("=") 0060 0061 if let key = tokens.first where key == "boundary" && tokens.count == 2 { 0062 boundary = tokens.last 0063 } 0064 } 0065 0066 if let boundary = boundary where boundary.utf8.count > 0 { 0067 0068 dispatch_async(dispatch_get_global_queue(0, 0), { 0069 0070 let multiparts = self.parseMultiPartFormData(request.body, boundary: "--\(boundary)") 0071 0072 for multipart in multiparts { 0073 if let fileName = multipart.fileName, 0074 let ext = fileName.split(".").last, 0075 let fieldName = multipart.name { 0076 0077 let name = self.randomStringWithLengthAndTime(10) 0078 let size = multipart.body.size 0079 let mimetype = MimeType.forExtension(ext) 0080 0081 let path = self.directory + name + "." + ext 0082 do { 0083 try Vaquita.writeDataSync(multipart.body, toFilePath: path) 0084 0085 let file = MultipartFile(name: name, ext: ext, size: size, 0086 mimetype: mimetype, originalName: fileName, 0087 fieldName: fieldName, path: path) 0088 0089 if request.files[fieldName] == nil { 0090 0091 request.files[fieldName] = [] 0092 } 0093 0094 request.files[fieldName]!.append(file) 0095 } catch let errorMessage { 0096 print("Boundry Error: \(errorMessage)") 0097 } 0098 0099 } else { 0100 if let value = multipart.value, let name = multipart.name { 0101 request.data[name] = value 0102 } 0103 } 0104 } 0105 0106 next() 0107 }) 0108 } else { 0109 next() 0110 } 0111 } 0112 0113 func randomStringWithLengthAndTime(length: Int) -> String { 0114 0115 let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".characters 0116 0117 let randomString: String 0118 0119 let lettersLength = UInt32(letters.count) 0120 0121 let randomCharacters = (0 ..< length).map { i -> String in 0122 #if os(Linux) 0123 let offset = Int(UInt32(rand()) % UInt32(lettersLength)) 0124 #else 0125 let offset = Int(arc4random_uniform(lettersLength)) 0126 #endif 0127 let c = letters[letters.startIndex.advancedBy(offset)] 0128 return String(c) 0129 } 0130 0131 randomString = randomCharacters.joinWithSeparator("") 0132 0133 let time = "\(NSDate().timeIntervalSinceReferenceDate)" 0134 0135 return "\(randomString)\(time.split(".").joinWithSeparator(""))" 0136 } 0137 0138 struct MultiPart
Multiparser.swift:187
    private func parseMultiPartFormData(data: Data, boundary: String) -> [MultiPart] {
Multiparser.swift:191
        var result = [MultiPart]()
Multiparser.swift:202
                                     boundary: String, isFirst: Bool) -> MultiPart? {
Multiparser.swift:227
        return MultiPart(headers: headers, body: body)
{ 0139 0140 let headers
Multiparser.swift:169
            return headers.reduce([String]()) { (currentResults: [String],
: [String: String] 0141 0142 let body: Data 0143 0144 var name: String? { 0145 return valueFor("content-disposition", parameterName: "name")?.unquote() 0146 } 0147 0148 var fileName: String? { 0149 return valueFor("content-disposition", parameterName: "filename")?.unquote() 0150 } 0151 0152 var value: String? { 0153 let string: String? 0154 do { 0155 string = try body.toString() 0156 } catch { 0157 string = nil 0158 } 0159 0160 if string?.characters.count > 0 { 0161 return string 0162 } else { 0163 return nil 0164 } 0165 } 0166 0167 private func valueFor
Multiparser.swift:145
            return valueFor("content-disposition", parameterName: "name")?.unquote()
Multiparser.swift:149
            return valueFor("content-disposition", parameterName: "filename")?.unquote()
(headerName: String, parameterName: String) -> String? { 0168 0169 return headers.reduce([String]()) { (currentResults: [String], 0170 header: (key: String, value: String)) -> [String] in 0171 0172 guard header.key == headerName else { 0173 return currentResults 0174 } 0175 let headerValueParams = header.value.split(";").map { $0.trim() } 0176 return headerValueParams.reduce(currentResults, combine: { (results:[String], token: String) -> [String] in 0177 let parameterTokens = token.split(1, separator: "=") 0178 if parameterTokens.first == parameterName, let value = parameterTokens.last { 0179 return results + [value] 0180 } 0181 return results 0182 }) 0183 }.first 0184 } 0185 } 0186 0187 private func parseMultiPartFormData(data: Data, boundary: String) -> [MultiPart] { 0188 0189 var generator = data.bytes.generate() 0190 0191 var result = [MultiPart]() 0192 0193 while let part = nextMultiPart(&generator, boundary: boundary, isFirst: result.isEmpty) { 0194 0195 result.append(part) 0196 0197 } 0198 return result 0199 } 0200 0201 private func nextMultiPart(inout generator: IndexingGenerator<[UInt8]>, 0202 boundary: String, isFirst: Bool) -> MultiPart? { 0203 if isFirst { 0204 guard nextMultiPartLine(&generator) == boundary else { 0205 return nil 0206 } 0207 } else { 0208 nextMultiPartLine(&generator) 0209 } 0210 0211 var headers = [String: String]() 0212 0213 while let line = nextMultiPartLine(&generator) where !line.isEmpty { 0214 0215 let tokens = line.split(":") 0216 0217 if let name = tokens.first, value = tokens.last where tokens.count == 2 { 0218 headers[name.lowercaseString] = value.trim() 0219 } 0220 0221 } 0222 0223 guard let body = nextMultiPartBody(&generator, boundary: boundary) else { 0224 return nil 0225 } 0226 0227 return MultiPart(headers: headers, body: body) 0228 } 0229 0230 private func nextMultiPartLine
Multiparser.swift:204
            guard nextMultiPartLine(&generator) == boundary else {
Multiparser.swift:208
            nextMultiPartLine(&generator)
Multiparser.swift:213
        while let line = nextMultiPartLine(&generator) where !line.isEmpty {
(inout generator: IndexingGenerator<[UInt8]>) -> String? { 0231 var result = String() 0232 while let value = generator.next() { 0233 if value > Multiparser.CR { 0234 result.append(Character(UnicodeScalar(value))) 0235 } 0236 if value == Multiparser.NL { 0237 break 0238 } 0239 } 0240 return result 0241 } 0242 0243 static let CR
Multiparser.swift:233
            if value > Multiparser.CR {
Multiparser.swift:268
                    if body.last == Multiparser.CR {
= UInt8(13) 0244 static let NL
Multiparser.swift:236
            if value == Multiparser.NL {
Multiparser.swift:264
                if body.last == Multiparser.NL {
= UInt8(10) 0245 0246 private func nextMultiPartBody(inout generator: IndexingGenerator<[UInt8]>, boundary: String) -> Data? { 0247 0248 var body = [UInt8]() 0249 0250 let boundaryArray = [UInt8](boundary.utf8) 0251 0252 var matchOffset = 0; 0253 0254 while let x = generator.next() { 0255 0256 matchOffset = ( x == boundaryArray[matchOffset] ? matchOffset + 1 : 0 ) 0257 0258 body.append(x) 0259 0260 if matchOffset == boundaryArray.count { 0261 0262 body.removeRange(Range<Int>(body.count - matchOffset ..< body.count)) 0263 0264 if body.last == Multiparser.NL { 0265 0266 body.removeLast() 0267 0268 if body.last == Multiparser.CR { 0269 body.removeLast() 0270 } 0271 } 0272 0273 return Data(bytes: body) 0274 } 0275 } 0276 return nil 0277 } 0278 0279 } 0280