/// <summary>
        /// This method allows the user to login to the management server with Root permissions.
        /// In order to use this method, the application must be run directly on the Management Server
        /// and to own super-user privileges.
        /// </summary>
        /// <param name="serverIpAddress">The IP address or name of the Check Point Management Server</param>
        /// <param name="payload">JSON object contains login command's arguments.</param>
        /// <returns><see cref="ApiLoginResponse"/> object</returns>
        private ApiLoginResponse LoginAsRoot(string serverIpAddress, JObject payload)
        {
            string systemEnvironment = Environment.GetEnvironmentVariable(MgmtCientExec);

            //checks
            if (systemEnvironment == null)
            {
                throw new ApiClientException("Failed to login as root, you are not running on the Management Server");
            }

            string pathFile = Path.Combine(systemEnvironment, ContextLoginAsRoot);

            if (!File.Exists(pathFile))
            {
                throw new ApiClientException("Failed to login as root, you are not running on the Management Server");
            }

            int     port               = _portResolver.GetPort(true);
            Process process            = InvokeLoginAsRoot(pathFile, payload, port);
            string  responseBodyString = GetResponseFromProcess(process);

            //Creating ApiResponse
            ApiLoginResponse loginResponse = new ApiLoginResponse(serverIpAddress, OkResponseCode, port, JObject.Parse(responseBodyString));

            return(loginResponse);
        }
        /// <summary>
        /// This function logs out from the server.
        /// </summary>
        /// <param name="loginResponse">The <see cref="ApiLoginResponse"/>- the response of the login command.</param>
        /// <returns>The <see cref=" ApiResponse"/> of the logout call.</returns>
        public ApiResponse Exit(ApiLoginResponse loginResponse)
        {
            if (loginResponse == null)
            {
                throw new ApiClientException("Error: login response argument is null");
            }

            ApiResponse response = ApiCall(loginResponse, "logout", "{}");

            return(response);
        }
        /// <summary>
        /// This function establishes an HttpsURL Connection.
        /// </summary>
        /// <param name="loginResponse">The <see cref="ApiLoginResponse"/> - the response of the login command.</param>
        /// <param name="url">The url.</param>
        /// <returns><see cref="HttpWebRequest"/></returns>
        private HttpWebRequest EstablishConnection(ApiLoginResponse loginResponse, Uri url)
        {
            if (!CheckFingerprint)
            {
                // no need to validate certification fingerprint, always accept
                ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => { return(true); };
            }
            else
            {
                ServicePointManager.ServerCertificateValidationCallback = delegate(object obj,
                                                                                   System.Security.Cryptography.X509Certificates.X509Certificate certificate,
                                                                                   System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors errors)
                {
                    // validate fingerprint hash
                    return(CompareFingerPrint(loginResponse.ServerIp, certificate.GetCertHashString()));
                };
            }

            // Create the web request
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

            if (_proxySettings.ProxySettingExist)
            {
                WebProxy myproxy = new WebProxy(_proxySettings.Host, _proxySettings.Port);
                myproxy.BypassProxyOnLocal = false;
                if (!string.IsNullOrEmpty(_proxySettings.UserName))
                {
                    myproxy.Credentials = new NetworkCredential(_proxySettings.UserName, _proxySettings.Password);
                }
                request.Proxy = myproxy;
            }

            request.Method      = "POST";
            request.ContentType = "application/json";
            request.Accept      = "*/*";
            request.UserAgent   = UserAgent;

            //In all API calls (except for login) the header containing the Check Point session-id is required.
            if (loginResponse.Sid != null)
            {
                request.Headers[SidHeader] = loginResponse.Sid;
            }

            return(request);
        }
        /// <summary>
        /// When the Management Server executes a time consuming command e.g: run-script, install-policy, publish,
        /// it will perform it asynchronously. In this case, a task-id will be returned to the user.
        /// The show-task command is used to receive the progress status and the result of the executed command.
        /// </summary>
        /// <param name="loginResponse"> The <see cref="ApiLoginResponse"/> - the response of the login command.</param>
        /// <param name="taskId">The tasks identifiers.</param>
        /// <returns>ApiResponse Result of show-task command</returns>
        public ApiResponse HandleAsyncTaskAsSync(ApiLoginResponse loginResponse, string taskId)
        {
            bool        taskComplete = false;
            ApiResponse taskResult   = null;

            // As long as there is a task in progress
            while (!taskComplete)
            {
                // Check the status of the task
                taskResult = ApiCall(loginResponse, ShowTaskCmd, "{\"task-id\": \"" + taskId + "\", \"details-level\": \"full\"}", false);
                if (taskResult == null)
                {
                    throw new ApiClientException("Error: failed to handle asynchronous task as synchronous, task result is undefined");
                }

                // Counts the number of tasks that are not in-progress
                int completedTasks = CountTaskNotInProgress(taskResult);

                // Get the total number of tasks
                int totalTasks = ((JArray)taskResult.Data["tasks"]).Count;

                // Are we done?
                if (completedTasks == totalTasks)
                {
                    taskComplete = true;
                }
                else
                {
                    try
                    {
                        Thread.Sleep(AsyncTaskSleepSeconds * 1000);
                    }
                    catch (Exception e)
                    {
                        throw new ApiClientException("Error: failed while 'sleep' function. Message: " + e.Message);
                    }
                }
            }

            //Check that the status of the tasks are not 'failed'
            CheckTasksStatus(taskResult);
            return(taskResult);
        }
        /// <summary>
        /// This function uses the login command to login into the management server.
        /// </summary>
        /// <param name="serverIpAddress">The IP address or name of the Check Point Management Server.</param>
        /// <param name="payload">String representing a JSON object containing the login command's arguments.</param>
        /// <returns><see cref="ApiLoginResponse"/> object</returns>
        public ApiLoginResponse Login(string serverIpAddress, string payload)
        {
            if (string.IsNullOrEmpty(serverIpAddress))
            {
                throw new ApiClientException("Error: server IP address argument is invalid");
            }

            int port = _portResolver.GetPort(false);
            ApiLoginResponse loginResponse = new ApiLoginResponse(serverIpAddress, OkResponseCode, port, new JObject());
            var apiCallResult    = ApiCall(loginResponse, "login", payload, false);
            var apiLoginResponse = apiCallResult as ApiLoginResponse;

            if (apiLoginResponse == null)
            {
                throw new ApiClientException("Failed to login to server");
            }

            return(apiLoginResponse);
        }
        /// <summary>
        /// This method receives a command query and returns the response - a list of all the desired objects.
        /// The method's purpose is to return a list with all of the desired objects, in contrast to the API's that return
        /// a list of a limited number of objects.
        /// </summary>
        /// <param name="loginResponse">The <see cref="ApiLoginResponse"/> - the response of the login command.</param>
        /// <param name="command">Name of the API command. This command should be an API that returns an array of objects</param>
        /// <param name="key">The items that the function collects.</param>
        /// <param name="payload">String representing a JSON object containing the command's arguments.</param>
        /// <returns><see cref="ApiResponse"/> that contains all the objects </returns>
        public ApiResponse ApiQuery(ApiLoginResponse loginResponse, string command, string key, string payload)
        {
            if (string.IsNullOrEmpty(payload))
            {
                throw new ApiClientException("Error: Payload argument is invalid, specify payload in json format");
            }

            JObject jsonPayload;

            try
            {
                jsonPayload = JObject.Parse(payload);
            }
            catch
            {
                throw new ApiClientException("Error: Payload argument is not in json format");
            }

            return(ApiQuery(loginResponse, command, key, jsonPayload));
        }
        /// <summary>
        /// When the Management Server executes a time consuming command e.g: run-script, install-policy, publish,
        /// server will perform it asynchronously. In this case a task-id is returned to the user.
        /// show--task command is used to receive the progress status and the result of the executed command.
        /// This method calls "show-task" in intervals of {<see cref="AsyncTaskSleepSeconds"/>} to check the
        /// status of the executed task.
        /// The function returns when the task (and all its sub - tasks) are no longer in-progress.
        /// </summary>
        /// <param name="loginResponse">The <see cref="ApiLoginResponse"/> - the response of the login command.</param>
        /// <param name="tasksId">The task identifier.</param>
        /// <returns><see cref="ApiResponse"/></returns>
        private ApiResponse HandleAsyncTasksAsSync(ApiLoginResponse loginResponse, JArray tasksId)
        {
            JArray tasks = new JArray();

            foreach (var task in tasksId)
            {
                string taskId = ((JObject)task)["task-id"].ToString();
                HandleAsyncTaskAsSync(loginResponse, taskId);
                tasks.Add(taskId);
            }

            ApiResponse taskResult = ApiCall(loginResponse, ShowTaskCmd, "{" + string.Format("\"task-id\":{0}, \"details-level\": \"full\"", tasks) + "}", false);

            if (taskResult == null)
            {
                throw new ApiClientException("Error: failed to handle asynchronous tasks as synchronous, tasks result is undefined");
            }

            //Check that the status of the tasks are not 'failed'
            CheckTasksStatus(taskResult);
            return(taskResult);
        }
        /// <summary>
        /// This method receives a command query and returns the response - a list of all the desired objects.
        /// The method's purpose is to return a list with all of the desired objects, in contrast to the API's that return
        /// a list of a limited number of objects.
        /// </summary>
        /// <param name="loginResponse">The <see cref="ApiLoginResponse"/> - the response of the login command.</param>
        /// <param name="command">Name of the API command. This command should be an API that returns an array of objects</param>
        /// <param name="key">The items that the function collects.</param>
        /// <param name="payload">The payload for the Api call</param>
        /// <returns><see cref="ApiResponse"/> that contains all the objects </returns>
        public ApiResponse ApiQuery(ApiLoginResponse loginResponse, string command, string key, JObject payload)
        {
            bool        finished      = false;             // Will become true after getting all of the data
            JArray      allObjects    = new JArray();      // Accumulate all of the objects from all the API calls
            int         iterations    = 0;                 // Number of times the API request has been called
            ApiResponse apiResponse   = null;              // API call response object
            JObject     offsetPayload = new JObject(payload);

            // Did we get all the objects?
            while (!finished)
            {
                // Make the API call, offset should be increased by limit with each iteration
                offsetPayload.Remove("limit");
                offsetPayload.Remove("offset");
                offsetPayload.Add("limit", LimitQuery);
                offsetPayload.Add("offset", iterations * LimitQuery);

                apiResponse = ApiCall(loginResponse, command, offsetPayload);

                iterations++;

                if (!apiResponse.Success)
                {
                    return(apiResponse);
                }

                JObject responsePayload = apiResponse.Data;
                if (responsePayload[key] == null || !responsePayload[key].HasValues || responsePayload["total"] == null)
                {
                    return(apiResponse);
                }

                // Total number of objects
                int totalObjects = int.Parse(responsePayload["total"].ToString());

                if (totalObjects == 0)
                {
                    return(apiResponse);
                }

                // Number of objects received so far
                int receivedObjects = int.Parse(responsePayload["to"].ToString());

                // Add the new objects to the objects list
                allObjects.Add(responsePayload[key]);

                // Were all the desired objects received
                if (receivedObjects == totalObjects)
                {
                    finished = true;
                }
            }

            // Creating a result list of all the objects
            apiResponse.Data.Remove("from");
            apiResponse.Data.Remove("to");

            // Replace the data from the last API call with the array of all objects.
            if (apiResponse.Data[key] != null)
            {
                apiResponse.Data.Remove(key);
            }
            apiResponse.Data.Add(key, allObjects);

            return(apiResponse);
        }
 /// <summary>
 /// This command sends a web-service API request to the management server.
 /// </summary>
 /// <param name="loginResponse">The <see cref="ApiLoginResponse"/> - the response of the login command.</param>
 /// <param name="command">The command name to be invoked.</param>
 /// <param name="payload">JSON object containing the command's arguments.</param>
 /// <param name="handleAsyncTaskAsSync">Determines the behavior when the API server responds with a "task-id".
 ///                                     by default, the function will periodically check the status of the task
 ///                                     and will not return until the task is completed.</param>
 ///<returns><see cref="ApiResponse"/> contains the server answer for the request.</returns>
 public ApiResponse ApiCall(ApiLoginResponse loginResponse, string command, JObject payload, bool handleAsyncTaskAsSync)
 {
     return(ApiCall(loginResponse, command, payload.ToString(), handleAsyncTaskAsSync));
 }
 /// <summary>
 /// This command sends a web-service API request to the management server.
 /// </summary>
 /// <param name="loginResponse">The <see cref="ApiLoginResponse"/> - the response of the login command.</param>
 /// <param name="command"> The command name to be invoked.</param>
 /// <param name="payload">JSON object contains command's arguments.</param>
 ///<returns><see cref="ApiResponse"/> containing the server's answer for the request.</returns>
 public ApiResponse ApiCall(ApiLoginResponse loginResponse, string command, JObject payload)
 {
     return(ApiCall(loginResponse, command, payload.ToString(), true));
 }
 /// <summary>
 /// This command sends a web-service API request to the management server.
 /// </summary>
 /// <param name="loginResponse"> The <see cref="ApiLoginResponse"/> - the response of the login command.</param>
 /// <param name="command">The command name to be invoked.</param>
 /// <param name="payload">String representing a JSON object contains command's arguments.</param>
 /// <returns><see cref="ApiResponse"/> containing the server's answer for the request.</returns>
 public ApiResponse ApiCall(ApiLoginResponse loginResponse, string command, string payload)
 {
     return(ApiCall(loginResponse, command, payload, true));
 }
        /// <summary>
        /// This command sends a web-service API request to the management server.
        /// </summary>
        /// <param name="loginResponse">The <see cref="ApiLoginResponse"/> of the login command.</param>
        /// <param name="command"> The command name to be invoked.</param>
        /// <param name="payload">String representing a JSON object containing the command's arguments.</param>
        /// <param name="handleAsyncTaskAsSync">Determines the behavior when the API server exec responds with a "task-id".
        ///                                     If TRUE, it will periodically checks the status of the task
        ///                                     and will not return until the task is completed.</param>
        /// <returns><see cref="ApiResponse"/> containing the server's answer for the request</returns>
        public ApiResponse ApiCall(ApiLoginResponse loginResponse, string command, string payload, bool handleAsyncTaskAsSync)
        {
            if (loginResponse == null)
            {
                throw new ApiClientException("Error: login response argument is null");
            }
            if (string.IsNullOrEmpty(command))
            {
                throw new ApiClientException("Error: 'command' argument is invalid");
            }

            // 1)  Establish Connection
            string         urlString = string.Format("{0}://{1}:{2}{3}{4}", UrlProtocol, loginResponse.ServerIp, loginResponse.Port, Context, command);
            Uri            url       = new Uri(urlString);
            HttpWebRequest request   = EstablishConnection(loginResponse, url);

            // Create a byte array of the data to be sent
            string data = payload ?? "{}";

            byte[] byteData = Encoding.UTF8.GetBytes(data);
            request.ContentLength = byteData.Length;

            ApiResponse res;

            try
            {
                // 2) Send request
                using (Stream requestStream = request.GetRequestStreamAsync().Result)
                {
                    requestStream.Write(byteData, 0, byteData.Length);
                }

                // 3) Get Response
                using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
                {
                    // Get the response stream
                    if (response == null)
                    {
                        throw new ApiClientException("Error: failed performing an I/O action, check that the server is up and " +
                                                     "running, and the certificate in the file is correct.\n If you use proxy " +
                                                     "server, define it in the ApiClientArgs object");
                    }

                    Stream stream = response.GetResponseStream();
                    if (stream == null)
                    {
                        throw new ApiClientException("Error: failed performing an I/O action, check that the server is up and " +
                                                     "running, and the certificate in the file is correct.\n If you use proxy " +
                                                     "server, define it in the ApiClientArgs object");
                    }

                    string responseJsonString = new StreamReader(stream).ReadToEnd();

                    // Creating ApiResponse
                    if (LoginCmd.Equals(command))
                    {
                        res = new ApiLoginResponse(loginResponse.ServerIp, (int)response.StatusCode, loginResponse.Port, JObject.Parse(responseJsonString));
                        // 4) When the command is 'login', hide the password so that it would not appear in the debug file.
                        data = ChangePasswordInData(data);
                    }
                    else
                    {
                        res = new ApiResponse(JObject.Parse(responseJsonString), (int)response.StatusCode);
                    }
                }
            }
            catch (WebException ex)
            {
                return(HandleApiCallWebException(ex));
            }
            catch (AggregateException ex)
            {
                return(new ApiResponse(ex.InnerExceptions[0]));
            }

            // 5) Store the request and the response (for debug purposes)
            if (_debugFile != null)
            {
                MakeApiCallLog(data, url, res);
            }

            // 6) If we want to wait for the task to end, wait for it
            if (handleAsyncTaskAsSync && res.Success && ShowTaskCmd.Equals(command))
            {
                if (res.Data["task-id"] != null)
                {
                    res = HandleAsyncTaskAsSync(loginResponse, res.Data["task-id"].ToString());
                }
                else if (res.Data["tasks"] != null)
                {
                    res = HandleAsyncTasksAsSync(loginResponse, (JArray)res.Data["tasks"]);
                }
            }

            return(res);
        }