<commit_before>//
//  APIHandler.swift
//  Prototype
//
//  Created by <NAME> on 17.06.15.
//  Copyright (c) 2015 <NAME>. All rights reserved.
//

import Foundation
import UIKit

let sharedInstance = APIHandler()

private let defaultBoundary = "------VohpleBoundary4QuqLuM1cE5lMwCy"

class APIHandler {
    let session: URLSession
    var appId: String! {
        return Bundle.main.object(forInfoDictionaryKey: "PrototyperAppId") as? String ?? UserDefaults.standard.string(forKey: UserDefaultKeys.AppId)
    }
    var releaseId: String! {
        return Bundle.main.object(forInfoDictionaryKey: "PrototyperReleaseId") as? String ?? UserDefaults.standard.string(forKey: UserDefaultKeys.ReleaseId)
    }
    
    var isLoggedIn: Bool = false
    
    init() {
        let sessionConfig = URLSessionConfiguration.default
        session = URLSession(configuration: sessionConfig)
    }
    
    class var sharedAPIHandler: APIHandler {
        return sharedInstance
    }
    
    // MARK: API Methods
    
    func fetchReleaseInformation(success: @escaping (_ appId: String, _ releaseId: String) -> Void, failure: @escaping (_ error : Error?) -> Void) {
        let bundleId = Bundle.main.infoDictionary?[kCFBundleIdentifierKey as String] as? String ?? ""
        let bundleVersion = Bundle.main.infoDictionary?[kCFBundleVersionKey as String] as? String ?? ""
        
        let url = URL(string: API.EndPoints.fetchReleaseInfo(bundleId: bundleId, bundleVersion: bundleVersion), relativeTo: API.BaseURL)!
        
        let request = jsonRequestForHttpMethod(.GET, requestURL: url)
        executeRequest(request as URLRequest) { (data, response, error) in
            guard let data = data else {
                failure(error)
                return
            }
            
            do {
                let dict = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Int]
                if let dict = dict, let appId = dict["app_id"], let releaseId = dict["release_id"] {
                    success("\(appId)", "\(releaseId)")
                } else {
                    failure(error)
                }
            } catch {
                failure(error)
            }
        }
    }
    
    func login(_ email: String, password: String,  success: @escaping (Void) -> Void, failure: @escaping (_ error : Error?) -> Void) {
        let params = postParamsForLogin(email: email, password: password)
        let articlesURL = URL(string: API.EndPoints.Login, relativeTo: API.BaseURL as URL?)
        
        guard let requestURL = articlesURL else {
            failure(NSError.APIURLError())
            return
        }
        
        guard let bodyData = try? JSONSerialization.data(withJSONObject: params, options: JSONSerialization.WritingOptions.prettyPrinted) else {
            failure(NSError.dataEncodeError())
            return
        }
        
        let request = jsonRequestForHttpMethod(.POST, requestURL: requestURL, bodyData: bodyData)
        executeRequest(request as URLRequest) { (data, response, networkError) in
            let httpURLResponse: HTTPURLResponse! = response as? HTTPURLResponse
            let error = (data == nil || httpURLResponse.statusCode != 200) ? NSError.dataParseError() : networkError
            error != nil ? failure(error) : success()
            self.isLoggedIn = error == nil
        }
    }
    
    func sendGeneralFeedback(description: String, name: String? = nil, success: @escaping (Void) -> Void, failure: @escaping (_ error : Error?) -> Void) {
        guard let appId = appId, let releaseId = releaseId else {
            print("You need to set the app and release id first")
            return
        }
        
        let url = URL(string: API.EndPoints.feedback(appId, releaseId: releaseId, text: description.escapedString, username: name), relativeTo: API.BaseURL)!
        
        let request = jsonRequestForHttpMethod(.POST, requestURL: url)
        executeRequest(request as URLRequest) { (data, response, error) in
            error != nil ? failure(error) : success()
        }
    }
    
    func sendScreenFeedback(screenshot: UIImage, description: String, name: String? = nil, success: @escaping (Void) -> Void, failure: @escaping (_ error : Error?) -> Void) {
        guard let appId = appId, let releaseId = releaseId else {
            print("You need to set the app and release id first")
            failure(nil)
            return
        }

        let contentType = "\(MimeType.Multipart.rawValue); boundary=\(defaultBoundary)"
        let bodyData = bodyDataForImage(screenshot)
        
        let url = URL(string: API.EndPoints.feedback(appId, releaseId: releaseId, text: description.escapedString, username: name), relativeTo: API.BaseURL)!
        
        let request = jsonRequestForHttpMethod(.POST, requestURL: url, bodyData: bodyData, contentType: contentType)
        executeRequest(request as URLRequest) { (data, response, error) in
            error != nil ? failure(error) : success()
        }
    }
    
    func sendShareRequest(for email: String, because explanation: String, name: String? = nil, success: @escaping (Void) -> Void, failure: @escaping (_ error : Error?) -> Void) {
        guard let appId = appId, let releaseId = releaseId else {
            print("You need to set the app and release id first")
            return
        }

        let url = URL(string: API.EndPoints.share(appId, releaseId: releaseId, sharedEmail: email, explanation: explanation, username: name), relativeTo: API.BaseURL)!
        
        let request = jsonRequestForHttpMethod(.POST, requestURL: url)
        executeRequest(request as URLRequest) { (data, response, error) in
            error != nil ? failure(error) : success()
        }
    }
    <commit_msg>fix crash because username was not escaped<commit_after>//
//  APIHandler.swift
//  Prototype
//
//  Created by <NAME> on 17.06.15.
//  Copyright (c) 2015 <NAME>. All rights reserved.
//

import Foundation
import UIKit

let sharedInstance = APIHandler()

private let defaultBoundary = "------VohpleBoundary4QuqLuM1cE5lMwCy"

class APIHandler {
    let session: URLSession
    var appId: String! {
        return Bundle.main.object(forInfoDictionaryKey: "PrototyperAppId") as? String ?? UserDefaults.standard.string(forKey: UserDefaultKeys.AppId)
    }
    var releaseId: String! {
        return Bundle.main.object(forInfoDictionaryKey: "PrototyperReleaseId") as? String ?? UserDefaults.standard.string(forKey: UserDefaultKeys.ReleaseId)
    }
    
    var isLoggedIn: Bool = false
    
    init() {
        let sessionConfig = URLSessionConfiguration.default
        session = URLSession(configuration: sessionConfig)
    }
    
    class var sharedAPIHandler: APIHandler {
        return sharedInstance
    }
    
    // MARK: API Methods
    
    func fetchReleaseInformation(success: @escaping (_ appId: String, _ releaseId: String) -> Void, failure: @escaping (_ error : Error?) -> Void) {
        let bundleId = Bundle.main.infoDictionary?[kCFBundleIdentifierKey as String] as? String ?? ""
        let bundleVersion = Bundle.main.infoDictionary?[kCFBundleVersionKey as String] as? String ?? ""
        
        let url = URL(string: API.EndPoints.fetchReleaseInfo(bundleId: bundleId, bundleVersion: bundleVersion), relativeTo: API.BaseURL)!
        
        let request = jsonRequestForHttpMethod(.GET, requestURL: url)
        executeRequest(request as URLRequest) { (data, response, error) in
            guard let data = data else {
                failure(error)
                return
            }
            
            do {
                let dict = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Int]
                if let dict = dict, let appId = dict["app_id"], let releaseId = dict["release_id"] {
                    success("\(appId)", "\(releaseId)")
                } else {
                    failure(error)
                }
            } catch {
                failure(error)
            }
        }
    }
    
    func login(_ email: String, password: String,  success: @escaping (Void) -> Void, failure: @escaping (_ error : Error?) -> Void) {
        let params = postParamsForLogin(email: email, password: password)
        let articlesURL = URL(string: API.EndPoints.Login, relativeTo: API.BaseURL as URL?)
        
        guard let requestURL = articlesURL else {
            failure(NSError.APIURLError())
            return
        }
        
        guard let bodyData = try? JSONSerialization.data(withJSONObject: params, options: JSONSerialization.WritingOptions.prettyPrinted) else {
            failure(NSError.dataEncodeError())
            return
        }
        
        let request = jsonRequestForHttpMethod(.POST, requestURL: requestURL, bodyData: bodyData)
        executeRequest(request as URLRequest) { (data, response, networkError) in
            let httpURLResponse: HTTPURLResponse! = response as? HTTPURLResponse
            let error = (data == nil || httpURLResponse.statusCode != 200) ? NSError.dataParseError() : networkError
            error != nil ? failure(error) : success()
            self.isLoggedIn = error == nil
        }
    }
    
    func sendGeneralFeedback(description: String, name: String? = nil, success: @escaping (Void) -> Void, failure: @escaping (_ error : Error?) -> Void) {
        guard let appId = appId, let releaseId = releaseId else {
            print("You need to set the app and release id first")
            return
        }
        
        let url = URL(string: API.EndPoints.feedback(appId, releaseId: releaseId, text: description.escapedString, username: name?.escapedString), relativeTo: API.BaseURL)!
        
        let request = jsonRequestForHttpMethod(.POST, requestURL: url)
        executeRequest(request as URLRequest) { (data, response, error) in
            error != nil ? failure(error) : success()
        }
    }
    
    func sendScreenFeedback(screenshot: UIImage, description: String, name: String? = nil, success: @escaping (Void) -> Void, failure: @escaping (_ error : Error?) -> Void) {
        guard let appId = appId, let releaseId = releaseId else {
            print("You need to set the app and release id first")
            failure(nil)
            return
        }

        let contentType = "\(MimeType.Multipart.rawValue); boundary=\(defaultBoundary)"
        let bodyData = bodyDataForImage(screenshot)
        
        let url = URL(string: API.EndPoints.feedback(appId, releaseId: releaseId, text: description.escapedString, username: name?.escapedString), relativeTo: API.BaseURL)!
        
        let request = jsonRequestForHttpMethod(.POST, requestURL: url, bodyData: bodyData, contentType: contentType)
        executeRequest(request as URLRequest) { (data, response, error) in
            error != nil ? failure(error) : success()
        }
    }
    
    func sendShareRequest(for email: String, because explanation: String, name: String? = nil, success: @escaping (Void) -> Void, failure: @escaping (_ error : Error?) -> Void) {
        guard let appId = appId, let releaseId = releaseId else {
            print("You need to set the app and release id first")
            return
        }

        let url = URL(string: API.EndPoints.share(appId, releaseId: releaseId, sharedEmail: email, explanation: explanation, username: name?.escapedString), relativeTo: API.BaseURL)!
        
        let request = jsonRequestForHttpMethod(.POST, requestURL: url)
        executeRequest(request as URLRequest) { (data, response, error) in
            error != nil ? failure(error) : success()
        }
    }
    
{'fraction_non_alphanumeric': 0.10208975676601575, 'fraction_numerical': 0.0027406646111682084, 'mean_word_length': 2.4919258373205744, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 27, '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': '1668361', 'n_tokens_mistral': 3260, 'n_tokens_neox': 3126, 'n_words': 886}