Giter Club home page Giter Club logo

libsuperuser's People

Contributors

afollestad avatar cernekee avatar chainfire avatar felixonmars avatar friederbluemle avatar mygod avatar pylersm avatar spocky avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

libsuperuser's Issues

Environment passing

Hi!

First of all, thank you for your work. I'm just learning right now your code, and during that i just noticed something:

public static List run(String shell, String[] commands, String[] environment, boolean wantSTDERR) {
[...]
// Combine passed environment with system environment
if (environment != null) {
newEnvironment.putAll(System.getenv());
[...]

So if there is no envrionment variable passed externally, then the other system environments will be skipped too. I might be wrong, but i thought i'll notice you about this.

Thanks!

Shell session could not terminate or stop

I looked into the code, but could not find the functionality of terminate or stop a shell session whether it is a interactive shell or not.
This feature is important for executing some commands like "tcpdump -p -vv -s 0 -w /sdcard/network_traffic.pcap" or "ps".

Gradle dependency error

Until before few days ago, I successfully compiled this application with same codes.
But since today, when I tried to build the application in android studio, I found a gradle error.

`Error:A problem occurred configuring project ':app'.

Could not resolve all dependencies for configuration ':app:_debugCompile'.
Could not resolve eu.chainfire:libsuperuser:1.0.0.+.
Required by:
android-msnlcollector:app:unspecified
> Could not resolve eu.chainfire:libsuperuser:1.0.0.201602232304.
> inconsistent module metadata found. Descriptor: eu.chainfire:libsuperuser:1.0.0.201602232303 Errors: bad version: expected='1.0.0.201602232304' found='1.0.0.201602232303'`

end/exit marker processing

If command that was executed in a shell doesn't print new line on the end, detecting command exit will not work properly.

Correct me if im wrong, this is my understandin of libsuperuser after quick look over the code....

libsuperuser marks end of command by echoing random string to stdout and stderror, and then checks for those lines during output parsing. When marker is found that means that command was finished.

STDIN.write(("echo " + command.marker + " $?\n").getBytes("UTF-8"));
STDIN.write(("echo " + command.marker + " >&2\n").getBytes("UTF-8"));

If last line on the actual command (command that user executed) is not new line (or doesnt end with new line (\n)), echos mentioned above will merge with last line of the actual output.
This is used to perform check if line is marker:

if (line.startsWith(command.marker))

which in this case will be false, because marker will actualy be on the end of the line, not a new line.

Am i correct, and can someone suggest a workaround.
Will something like this work?

STDIN.write(("echo \n" + command.marker + " $?\n").getBytes("UTF-8"));
STDIN.write(("echo \n" + command.marker + " >&2\n").getBytes("UTF-8"));

Just an example:
libsuperuser will never finish command from this program:

int main(int argc, char **argv)
{
    printf("no new line at the end");
    return 0;
}

Can't import

I get this:

image

Also, BTW, you can remove the "buildToolsVersion" part. It's not needed anymore, for a long time...

Smaller library

I am working on app which has around 90 Kb APK file. I just tried to put some simple Shell.SH.run code added compile 'eu.chainfire:libsuperuser:1.0.0.+' to gradle file and final APK had above 550 Kb.

Since library is just code, not images or so, I wonder if is possible to shrink it.

Unit Tests for improved test coverage

Hi there,

My name is Farid. I'm a developer with great interest in making open source contributions to popular projects.

My company - DevFactory - is sponsoring me to improve unit test coverage in open source projects.

I have analyzed libsuperuser and observed that there is room for improvement of coverage. The results indicate that the project currently has no unit test coverage.

If you are interested in having us work towards improving the project’s coverage to 80%, please let me know and we will add it to our pipeline. Our first step will be to create a pull request with a sample. Once you approve it, we'll follow up with one or two more pull requests. Our target is to increase code coverage to above 80 percent.

For an example of our work, please see these Pull Requests accepted by the community:

I'm looking forward to your confirmation.

Thank you,
Mohd Farid
Open Source Code Coverage Team
DevFactory

Updating to 1.0.0.201607041850 caused blocking issues

I was on 1.0.0.201602271131 and previous versions and everything worked great. When it updated to 1.0.0.201607041850 I started getting complaints from users that things were taking forever to run (things that took root, basically just Shell.SU.available() and one Shell.SU.run(). When I put it back to 1.0.0.201602271131 it worked fine. I would be happy to provide whatever information that would be helpful.

How to start interactive mode and run operations of it on a background thread?

It seems the only way to start interactive mode is by using a listener.
When I try to avoid this, only when root permission is given, I get the listener being called, but if the root permission isn't given, the listener isn't called.

I've used the exact same function calls as on the sample, but it still behaves this way.

Is there a way to start interactive mode on the background thread?
Same goes about running commands using interactive mode on a background thread.

I could use rootSession.addCommand(String) , and then rootSession.waitForIdle() , but then I lose the output lines that were written...

maven package missing

This seems to no longer be available on Maven Central. Adding compile 'eu.chainfire:libsuperuser:1.0.0+' results in a failed to find error. Manually searching Maven Central via the dialog in Android Studio or via search.maven.org does not find any package either.

Binary stdout

Currently all shell methods I know of look like

List Shell.SH.run(String command)

in that they return a list of lines (excluding \n) of standard output. Surely, this shouldn't work for binary output: What if there are no newline characters, what if there are, what if there are value-zero characters, what if the current String encoding is UTF-16?

How does one get byte[] output instead?

Segmentation Fault on Nexus 10

Running the super user example (Shell.SU.available()) gives the following error and a tombstone file is created, however the app does not crash. Any specific reason why this can happen?

04-01 17:00:38.275: I/DEBUG(118): Build fingerprint: 'google/mantaray/manta:4.3/JWR66Y/776638:user/release-keys'
04-01 17:00:38.275: I/DEBUG(118): Revision: '9'
04-01 17:00:38.275: I/DEBUG(118): pid: 4548, tid: 4548, name: AsyncTask #2 >>> eu.chainfire.libsuperuser_example <<<
04-01 17:00:38.275: I/DEBUG(118): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 748e0390
04-01 17:00:38.285: W/NativeCrashListener(365): Couldn't find ProcessRecord for pid 4548

Shell::run() doesn't return the result if the command contains "exit"

Writing "exit" to STDIN in Shell.java:152 fails if the command contains "exit", because the STDIN is already closed. This results in IOException, which is handled on Shell.java:178. This trashes the result, even though the command was successful.

I'm not sure what is the right way to fix this - sure, I can not use exit in the script, but I think the library should be able to handle it. Maybe nest in another try-catch block just around that exit line and ignore if it fails?

OnLineListener per command like OnCommandResultListener

It would be nice to have an OnLineListener per command like the OnCommandResultListener. This would enable to add commands with big outputs to the interactive shell without worrying that it will exhaust memory.

After having some problems with my own Shell implementation and with all the upcoming problems of Android 4.5, it would be nice to base all root apps on libsuperuser.
Thus, I am trying to port my own library root-commands (https://github.com/dschuermann/root-commands) to use libsuperuser for the actual shell access.

This requested feature is the only requirement left for my migration.

cannot open project

ERROR: No toolchains found in the NDK toolchains folder for ABI with prefix: mipsel-linux-android

Android Studio 3.3.2

Gradle file is deprecated

android-library is a deprecated plugin, it's now com.android.library.

Also, the latest buildToolsVersion is 21.0.2 and the latest targetSdk is 21:)

Shell.SU.Run does not return

I am using libsuperuser, by importing the following:

import eu.chainfire.libsuperuser.Application;
import eu.chainfire.libsuperuser.Shell;

In the class I got the following method:

    private List<String> suRun(String format, Object... args) {
        String binDir = mAppContext.getFilesDir() + "/bin/";
        String command = binDir + String.format(format, args);
        return Shell.SU.run(command);
    }

and in another method, I call it as follows:

    List<String> result = suRun("cs close %s", getVolumePath());

the command does run, yet it doesn't seem to return, here's the relevant logcat output:

D/libsuperuser( 9783): [libsuperuser][C][SU%] START
D/libsuperuser( 9783): [libsuperuser][C][SU+] /data/data/me.opsec.darkmatter/files/bin/cs close /extSdCard/volume.dat
D/libsuperuser( 9783): [libsuperuser][O][SU*] failed: No such file or directory
D/libsuperuser( 9783): [libsuperuser][O][SU*] failed: No such file or directory
D/libsuperuser( 9783): [libsuperuser][O][SU*] failed: No such file or directory
D/libsuperuser( 9783): [libsuperuser][O][SU*] failed: No such file or directory
D/libsuperuser( 9783): [libsuperuser][O][SU*] failed: Invalid argument

as far as I understand, I should expect a [SU%] END in the logcat, but I never get it.
it seems to me that process.waitFor() in Shell.java never returns.

Provide access to return codes when possible

It would be enormously useful to have access to the return codes of commands even if it is not guaranteed for non-zero return codes.
something like gobblers or a callback handler would be great.

SuperSU ROM Building

Hi,
I've been trying to integrate SuperSU into an AOSP 4.4.4 ROM but am having a lot of difficulties.
I have everything properly configured in the make files to copy over the su, daemonsu and install-recovery.sh files but it seems that no matter what I do (chmoding and repacking system images, modiying the init script) that /system/etc/install-recovery.sh is always set with 0644 permissions and that even adding the "/system/xbin/daemonsu --auto-daemon &" command as a seperate init.rc service doesn't change it

I was wondering if you could clarify the process as it's extremely frustrating and I'm sure I'm not the only person having difficulties with this

The Shell.SU.shell() method always returns su rather than context

When trying to use the Shell.SU.shell(int uid, String context) method to get a context, it will always return "su" rather than the actual shell string including the context. This is a result an issue with the Shell.SU.version(boolean internal) method.

Changing the shell to sh rather than the su command and passing su -v as a command allows this method to work properly (at least on the devices I've tested on).

See below for fixed method code:

public static String version(boolean internal) {
            List<String> ret = Shell.run(
                    "sh", 
                    new String[] {internal ? "su -V" : "su -v" }, 
                    null,
                    false
            );
            if (ret == null) return null;

            for (String line : ret) {
                if (!internal) {
                    if (line.contains(".")) return line;                    
                } else { 
                    try {
                        if (Integer.parseInt(line) > 0) return line;
                    } catch(NumberFormatException e) {                  
                    }
                }
            }
            return null;
        }

Gradle dependencies error

Hi, the compile has changed in the gradle? because i use your library for listing my process in background and the library gives me this error:

Error:(38, 13) Failed to resolve: eu.chainfire:libsuperuser:1.0.0.+

By the way, your library is great Chainfire!

Cheers!

Is it possible to send CTRL-C?

I'm trying to execute screenrecord and it seems that the only way to stop it is to send CTRL-C or simply wait for 3 min limit time. The worst part is while screenrecord is active, I cannot execute other commands until screenrecord process stops.

Is it possible to send CTRL-C to Shell.SU.run()? Or perhaps multiple threads of ADB Shell so I can use 1 for screenrecord and another for killing the process of screenrecord. You know, like when you have 2 windows on your Terminal.

Thank you.

How to add dependency to Gradle?

Just a tiny question for this great library please:

How do I add the dependency of this library to Android-Studio? What exactly should I do?

Shell.Interactive should not run availableTestCommands

When creating an interactive shell the Shell.availableTestCommands are run after the initial commands. This will only happen if the onCommandResultListener is not null.

TEST:

new Thread() {
  @Override
  public void run() {
      String[] commands = {
              "echo foo",
              "sleep 1",
              "echo bar",
              "sleep 1",
              "echo baz"
      };

      new Shell.Builder()
      .setShell("sh")
      .setOnSTDOUTLineListener(new Shell.OnCommandLineListener() {

        @Override
        public void onLine(String line) {
            android.util.Log.d("ShellTest", line);
        }

        @Override
        public void onCommandResult(int commandCode, int exitCode) {

        }
    })
    .addCommand(commands)
    .open(new Shell.OnCommandResultListener() {

        @Override
        public void onCommandResult(int commandCode, int exitCode, List<String> output) {
            android.util.Log.d("ShellTest", String.format("finished with exit code %d", exitCode));
        }
    });
  }
}.start();

LOG:

D/ShellTest(10309): foo
D/ShellTest(10309): bar
D/ShellTest(10309): baz
D/ShellTest(10309): -BOC-
D/ShellTest(10309): uid=10177(u0_a177) gid=10177(u0_a177) groups=1015(sdcard_rw),1028(sdcard_r),3003(inet),9997(everybody),50177(all_a177) context=u:r:untrusted_app:s0
D/ShellTest(10309): finished with exit code 0

If the interactive shell is opened with commands then the attempt to give time for the dialog to show will be useless.

run() does not return null on failure

Shell.SU.run("echo foo > bar"); always returns an empty list instead of null, even if I decline the SuperSU request.
I'd like to present the user the most exact error message possible, so I'd like to know if the issue is because there was no su access or if the command failed.

Currently, I have to do a Shell.SU.available() check before issuing my command.

Device: Nexus 5x on Marshmallow.

Question: How to stream from a given inputStream into a root-command outputStream?

It seems that sometimes, it's needed to stream data from an InputStream into the outputStream of a root command.

Example can be found on this repository (which demonstrates how to install split-apks using root) :
https://github.com/Aefyr/SAI

If you look at itsRootedSAIPackageInstaller.java file, you can see it's calling this:

while (apkSource.nextApk())
     ensureCommandSucceeded(Root.exec(String.format("pm install-write -S %d %d \"%s\"", apkSource.getApkLength(), sessionId, apkSource.getApkName()), apkSource.openApkInputStream()));

And the code for its root class is as such:

    private static Result execInternal(String command, @Nullable InputStream inputPipe) {
        try {
            Process process = Runtime.getRuntime().exec(String.format("su -c %s", command));

            StringBuilder stdOutSb = new StringBuilder();
            StringBuilder stdErrSb = new StringBuilder();
            Thread stdOutD = writeStreamToStringBuilder(stdOutSb, process.getInputStream());
            Thread stdErrD = writeStreamToStringBuilder(stdErrSb, process.getErrorStream());

            if (inputPipe != null) {
                IOUtils.copyStream(inputPipe, process.getOutputStream());
                inputPipe.close();
                process.getOutputStream().close();
            }

            process.waitFor();
            stdOutD.join();
            stdErrD.join();

            return new Result(command, process.exitValue(), stdOutSb.toString().trim(), stdErrSb.toString().trim());
        } catch (Exception e) {
            Log.w(TAG, "Unable execute command: ");
            Log.w(TAG, e);
            return new Result(command, -1, "", "Java exception: " + Utils.throwableToString(e));
        }
    }

What is the equivalent for this on libsuperuser ?

how to su

#63
Updating to 1.0.0.201607041850 caused blocking issues

Root lost after restarting Bluestacks 2

Hello,

I was trying to install SuperSU binaries on Bluestacks 2, because it has "su" execution exploit and some apps are not working correctly with "su" exploit. After installation, SuperSU is working perfectly until i restart Bluestacks, and the "su" execution is not working anymore. root is completely lost and i'm not able to root Bluestacks with any of root apps and SuperSU. I have tried to enable OTA survival before reproduce this, but it didn't help. SuperSU binary and recovery script are still there but it can't execute "su"!

I have tried to root Bluestacks with Kingroot, restart it and the root was permanent. root is working perfectly and it never go away.

Can you or someone try to find out what cause "su" execution not to work even it is still installed?

Unable to cat ftrace buffer to a secondary user directory

I'm playing with the ftrace on the Nexus 6 with Lollipop. Everything works as expected except saving the trace buffer "/d/tracing/trace" to the secondary user storage directory using the "cat" command as follows. The number 10 indicates the secondary user who logged in and the storage path is gotten from the Environment. The file may be created but the content is not written so the size is zero.

cat /d/tracing/trace > /storage/emulated/10/Download/trace.log

On the other hand, if it is the primary user, the same command works as expected and the trace buffer is fully written to the primary user's directory.

cat /d/tracing/trace > /storage/emulated/0/Download/trace.log

I'm wondering if there is something missing here. Any idea?

PS: both uses SU.

ls -pl doesn't work nor ls -Al

I want to know which of the files are directory. So I am using the ls -pl command. But it returns me 0 results. When I tried it with Terminal Emulator app or Adb, I do get the results? Any way to achieve this? My main idea is to know if the file is directory or not?

`

                                     String [] commands = new String[1];

                    commands[0] = "ls -pl " + path; // path --> /storage/emulated

                    List<String> suResult = Shell.SU.run(commands);

                    StringBuilder sb = new StringBuilder();

                    for (String line : suResult) {

                        sb.append(line).append((char)10);

                    }
                    Logger.log("TAG","List=="+sb);`    

ADB results:
`

                   root@bacon:/ # ls -pl /storage/emulated

total 24

drwxrwx--x 71 root sdcard_rw 4096 2016-07-18 23:33 0/

drwxrwx--x 2 root sdcard_rw 4096 2016-05-12 16:18 legacy/

drwxrwx--x 3 root sdcard_rw 4096 2016-07-15 17:15 obb/ `

Paths to external app cache folder

How do I get to the path of Context.getExternalCacheDir() using this shell? In the lib I was currently using (org.sufficientlysecure.rootcommands), I could just do (in Kotlin): context.externalCacheDir.absolutePath.replace("/storage/emulated/0","\$EXTERNAL_STORAGE") and it worked, with this lib it doesn't. Is there any difference? How could I accomplish the same thing across all device models?

Shell.SU.run() does not always return command result

Happening with: Nexus 4 running Android Marshmallow with SuperSu installed and properly working. Dont know if happens with other Android versions or other devices (but I guess so).

Steps to reproduce: Running sample command

Shell.SU.run("pm revoke io.plaidapp android.permission.INTERNET");

will result in a empty String array, while running the same command through ADB Shell terminal (from the PC) will result in the following sentence 'Operation not allowed: java.lang.SecurityException: Can't change android.permission.INTERNET. It is required by the application'

Suggestion: Either return null (because it throws java.lang.SecurityException) or return the whole message as a String

capture

PING command takes longer to execute if there is an error than when running from ADB terminal.

Hello,

I am continuously sending PING commands to a host in order to check whether it is reachable.
The shell is initialized as per your example:

   rootSession = new Shell.Builder().
            useSU().
            setWantSTDERR(true).
            setWatchdogTimeout(5).
            setMinimalLogging(true).open();

However, if the host is unreachable there will be no callback at all (not even with WATCHDOG_EXIT) and sending any further commands will not produce responses as well, until I call rootSession.close() and then open() again.

The addCommand() method is used to send the command and everything is working as expected until the point where the host becomes unreachable.

I am testing the same command in the terminal over ADB and after 2 seconds it finishes with Exit Code 1 and a Destination Host Unreachable error (as expected):

root@hltexx:/ # ping -c 1 192.168.100.50
PING 192.168.100.50 (192.168.100.50) 56(84) bytes of data.
From 192.168.100.109: icmp_seq=1 Destination Host Unreachable

--- 192.168.100.50 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms

1|root@hltexx:/ #

Unfortunately I was not able to further debug this as I recently started using Android Studio and the debugger there is slower than evolution. :(

I will get back with more information when I import my project back in Eclipse.

Keep shell open but kill a command

The situation:

I am writing a file manager and I am using FileObserver to watch for any changes in the current directory. While browsing directories with no read access I am running inotifywait -m in a root shell.

The process runs forever. When a user navigates to another directory I am calling shell.kill() and then adding a new command (inotifywait [OPTIONS] [FILE]) to listen to the new working directory.

The issue/request/question:

When running a command that never terminates (like logcat or inotifywait) is there a way to stop that command and run another command without requesting root access again (starting a new shell process)?

I don't want the SuperSU toast to popup every time I need to kill the process and add another command.

If it is of any help, here is my code: http://pastebin.com/kG9Cjd4D

Gradle support / git tags

From your commits I guess you're still using Eclipse, but would you mind adding Gradle support? I'm already using it in my own branch (https://github.com/ramdroid/libsuperuser/blob/gradle/libsuperuser/build.gradle) but unfortunately I have to upload it to my own mvn-repo on github. So it would be nice if everyone could just pull the newest version from maven central instead ;)

I also would love if you'd support some kind of versioning to your library (e.g. in build.gradle + using git tags). In the current situation when including it in my projects I have no clue what state I'm using...

Can't read output from STDERR

I have a use case when all output is written to STDERR. I modified the libsuperuser_example project to reproduce:

suResult = Shell.run("su", new String[] {
    "id",
    "ls -l / >/dev/stderr"
}, null, true);

Now the output from ls is no longer included in "suResult".

While debugging I've seen that the StreamGobbler STDERR is initialized but for some reason never reaches run() !?!?!

If the user clicks "deny", no callbacks are executed

I want to make a su call while setting a context. The synchronous interface in SU.run doesn't support contexts, so I am using the interactive shell. I have this code:

final boolean[] res = new boolean[1];
res[0] = false;

rootSession = new Shell.Builder().
    useSU().
    setWantSTDERR(true).
    setWatchdogTimeout(timeout).
    setMinimalLogging(false).
    open(new Shell.OnCommandResultListener() {
        @Override
        public void onCommandResult(int commandCode, int exitCode, List<String> output) {
            // Callback to report whether the shell was successfully started up

            if (exitCode != Shell.OnCommandResultListener.SHELL_RUNNING) {
                Log.e(TAG, "Error opening root shell: exitCode " + exitCode);
            } else {
                rootSession.addCommand(command, 0, new Shell.OnCommandResultListener() {
                    public void onCommandResult(int commandCode, int exitCode, List<String> output) {
                        if (exitCode < 0) { 
                            Log.e(TAG, "Error executing command: exitCode " + exitCode);
                        } else {
                            res[0] = true;
                        }
                    }
                });
            }
        }
    });

rootSession.waitForIdle();
rootSession.close();
return res[0];

(The res[0] is a bit wacky, but I can't think of another way to force this into a synchronous function and return a value).

If the user presses "Deny" on the super user dialog, my callback is never executed. This is because the thread that runs it has no looper, and the code in "handleWatchdog" only calls the callbacks if a handler is defined:

https://github.com/Chainfire/libsuperuser/blob/master/libsuperuser/src/eu/chainfire/libsuperuser/Shell.java#L1242

I'm not sure if this is contrary to the documentation, which states that callbacks will be called from the threads, or not (the docs only refer to the gobbler threads).

In any case, I'm a bit at a loss as to how to use the Shell interface from my non-main thread. I can live with the above hack, but I have to catch the deny action somehow.

(I tried the rewrite the code above the use a looper, but currently running into problems where my app segfaults after calling Looper.quit()).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.