/*
 * Copyright (C) 2013 - 2016 Alexander Martinz
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 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 General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package alexander.martinz.libs.execution;

import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.WorkerThread;
import android.text.TextUtils;
import android.util.Log;

import java.io.File;

public class RootCheck {
    private static final String TAG = RootCheck.class.getSimpleName();

    private static final String[] PATH_SU = new String[]{
            "/system/bin/su", "/system/xbin/su", "/system/bin/.ext/.su", "/system/xbin/sugote",
            // "system less" root (supersu)
            "/su/bin/su"
    };

    private static Boolean sIsRooted = null;
    private static String sSuVersion = null;

    /**
     * @return true if the device is rooted, false if not
     * <p/>
     * The result is cached, for a non cached result, use {@link RootCheck#isRooted(boolean)}
     */
    public static boolean isRooted() {
        return isRooted(false);
    }

    /**
     * @param forceCheck Whether to use the cached result or force a new check
     * @return true if the device is rooted, false if not
     */
    public static boolean isRooted(boolean forceCheck) {
        if (!forceCheck && sIsRooted != null) {
            return sIsRooted;
        }

        final String suPath = getSuPath();
        if (!TextUtils.isEmpty(suPath)) {
            if (ShellLogger.DEBUG) {
                Log.d(TAG, String.format("Found su path: %s", suPath));
            }
            sIsRooted = true;
            return true;
        }
        if (ShellLogger.DEBUG) {
            Log.d(TAG, "no su binary found, trying with hit and miss");
        }

        // fire and forget id, just for fun
        RootShell.fireAndForget("id");

        final RootShell rootShell = ShellManager.get().getRootShell();
        sIsRooted = (rootShell != null);
        if (ShellLogger.DEBUG) {
            Log.d(TAG, String.format("is rooted: %s", sIsRooted));
        }
        return sIsRooted;
    }

    @WorkerThread @NonNull public static String getSuVersion() {
        return getSuVersion(false);
    }

    @WorkerThread @NonNull public static String getSuVersion(boolean forceCheck) {
        if (forceCheck || sSuVersion == null) {
            final boolean hasRoot = isRooted();
            final String version = hasRoot ? RootShell.fireAndBlockString("su -v") : "-";
            sSuVersion = TextUtils.isEmpty(version) ? "-" : version;
        }
        return sSuVersion;
    }

    /**
     * @return The path of the su binary or null if none found
     */
    @Nullable public static String getSuPath() {
        for (final String path : PATH_SU) {
            if (new File(path).exists()) {
                return path;
            }
        }
        return null;
    }
}

@@ -1308,22 +1308,70 @@
 Boolean 
-sIsRoo
+isRooted = null;%0A    private static Boolean isRootGran
 ted = nu
@@ -1401,17 +1401,16 @@
 String s
-S
 uVersion
@@ -1914,18 +1914,17 @@
 heck && 
-sI
+i
 sRooted 
@@ -1945,34 +1945,33 @@
          return 
-sI
+i
 sRooted;%0A       
@@ -2186,34 +2186,33 @@
   %7D%0A            
-sI
+i
 sRooted = true;%0A
@@ -2525,18 +2525,17 @@
         
-sI
+i
 sRooted 
@@ -2648,19 +2648,872 @@
 s%22, 
-sI
+isRooted));%0A        %7D%0A        return isRooted;%0A    %7D%0A%0A    /**%0A     * @return true if the device is rooted and root is granted, false if not%0A     * %3Cp/%3E%0A     * The result is cached, for a non cached result, use %7B@link RootCheck#isRootGranted(boolean)%7D%0A     */%0A    @WorkerThread public static boolean isRootGranted() %7B%0A        return isRootGranted(false);%0A    %7D%0A%0A    /**%0A     * @param forceCheck Whether to use the cached result or force a new check%0A     * @return true if the device is rooted and root is granted, false if not%0A     */%0A    @WorkerThread public static boolean isRootGranted(boolean forceCheck) %7B%0A        if (!forceCheck && isRootGranted != null) %7B%0A            return isRootGranted;%0A        %7D%0A%0A        // no root available means we can not get root granted as well%0A        if (!i
 sRooted
+(
 ))
+ %7B%0A            isRootGranted = false;%0A            return false
 ;%0A  
@@ -3516,32 +3516,33 @@
 ;%0A        %7D%0A
+%0A
         
 return sIsRo
@@ -3533,21 +3533,325 @@
     
-return sIsRoo
+final String result = RootShell.fireAndBlockString(%22id%22);%0A        if (TextUtils.isEmpty(result)) %7B%0A            // we did not get any result, means the shell did not work%0A            isRootGranted = false;%0A            return false;%0A        %7D%0A%0A        isRootGranted = result.contains(%22uid=0%22);%0A        return isRootGran
 ted;
@@ -4076,17 +4076,16 @@
 eck %7C%7C s
-S
 uVersion
@@ -4247,17 +4247,16 @@
        s
-S
 uVersion
@@ -4328,17 +4328,16 @@
 return s
-S
 uVersion

add check if root is granted