Giter Site home page Giter Site logo

badcow / dns Goto Github PK

View Code? Open in Web Editor NEW
256.0 256.0 37.0 908 KB

The aim of this project is to create abstract object representations of DNS records in PHP. The project consists of various classes representing DNS objects (such as Zone, ResourceRecord, and various RData types), a parser to convert BIND style text files to the PHP objects, and builders to create aesthetically pleasing BIND records.

License: MIT License

PHP 100.00%
bind dns named php web

dns's People

Contributors

a3dho3yn avatar adamnicholson avatar fbett avatar livda avatar necrogami avatar samuelwilliams avatar scrutinizer-auto-fixer avatar skirmis avatar sloeddy avatar srsbiz avatar tomschlick avatar yeganemehr 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

dns's Issues

Update parser to read the comments

A ResourceRecord have an attribute comment and the builders write them, but we lose the comments on the reading of the file previously generated by the builder. Is it's possible to improve the parser and have the comments in the ResourceRecord object ?

Explicit support for PHP 8.0

Badcow/DNS Version 4.1 provides explicit support for PHP 8.0 but the "rlanvin/php-ip": "^2.0" is not supporting PHP 8.0 right now

Other Records Types

SRV
DNSSEC

It's a great library and i'd love to use it if i had these other entry types.

Not a valid resource record name

PHP Fatal error: Uncaught Badcow\DNS\DNSException: "google._domainkey" is not a valid resource record name. in /Users/necrogami/code/dt/vendor/badcow/dns/lib/ResourceRecord.php:96
Stack trace:
#0 /Users/necrogami/code/dt/vendor/badcow/dns/lib/ResourceRecord.php(59): Badcow\DNS\ResourceRecord->setName('google._domaink...')
#1 /Users/necrogami/code/dt/random.php(88): Badcow\DNS\ResourceRecord->__construct('google._domaink...')
#2 {main}
thrown in /Users/necrogami/code/dt/vendor/badcow/dns/lib/ResourceRecord.php on line 96

Code Snippet

$txt3 = new ResourceRecord('google._domainkey');
$txt3->setRdata(Factory::txt('v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDazaxHRVRVE1vnA3j02HvwgWcIhs2RWZ4U0aXknRapSSeTolKvFgnS+EYRRs8THeUdUDSiGYl5avuru10oIxNbcActybF+YIPClGdGGaGXVFboAs/EZFdUfHrCop/9DzxqS1jYHp33d+P9xoVi8ouQFs1AzoyyBVR0gwbIq8EIHQIDAQAB'));
$zone->addResourceRecord($txt3);

Get a new version

Have you plan to make many more updates to this lib before creating a v1.1 or a v1.0.1 ? I'll be glad if the update you've just merged could be used not only by pulling master

TXT records without quotation marks ignore content after first whitespace

For a TXT record like example.org. TXT 300 v=spf1 mx include:spf.example.com -all the parser ignores the content after the first space.

TXT records are allowed to have multiple "character strings" so this behaviour is valid

I replaced the fromText method to resolve the issue. This also fixes content with multiple quoted strings, like "foo bar" "foo baz"

public function fromText(string $text): void
			{
				$string = new StringIterator($text);
				$txt = new StringIterator();

				while ($string->valid()) {
					if ($string->is(static::WHITESPACE)) {
						$string->next();
						continue;
					}

					if ($string->is(Tokens::DOUBLE_QUOTES)) {
						self::handleTxt($string, $txt);
						$string->next();
						$txt->append(' ');
						continue;
					}

					static::handleContiguousString($string, $txt);
					$string->next();
					$txt->append(' ');
				}

				$this->setText(trim((string) $txt), true);
			}

Underscore missing in Validator::fullyQualifiedDomainName

Hi,

When parsing this (valid and working) record

testnaptr.at. 30 IN NAPTR 100 50 "s" "SIP+D2U" "" _sip2._udp.testnaptr.at.

I got this exceptions

Could not extract Rdata from resource record "testnaptr.at. 30 IN NAPTR 100 50 "s" "SIP+D2U" "" _sip2._udp.testnaptr.at.".
Replacement must be a fully qualified domain name. "_sip2._udp.testnaptr.at." given

The replacement is a valid FQDN, but the Validator::fullyQualifiedDomainName method is missing the underscore in the regexp.

Best,
Michael

Quoted Strings

If I understand the corresponding RFC correctly (see 3.3.14. TXT RDATA format) , TXT records need to be in the following format: TXT-DATA One or more <character-string>s. where <character-string> is defined like this:

<character-string> is expressed in one or two ways: as a contiguous set
of characters without interior spaces, or as a string beginning with a "
and ending with a ".  Inside a " delimited string any character can
occur, except for a " itself, which must be quoted using \ (back slash).

To the best of my understanding this means that both of the following records are valid:

zone.tld.	900	IN	TXT	"foo bar"
zone.tld.	900	IN	TXT	foobar

Originally posted by @lorenzbausch in #35 (comment)

add specific topics

can you add some specific topics to this repo ๐Ÿ˜. like dns, bind, web, named ...

AlignedRdataFormatters::TXT() breaks Google site verification

Since moving over to using this library for some of our DNS handling, we've notice that google site verification is now broken for new domains.

This appears to be due to the fact that the above mentioned method is splitting the TXT records at 40 characters, presumably just for easier readability.

This results in split strings in the resulting record. From what I can gather, they should be concat'ing these strings together, but that does not appear to be happening.

After further reading, I found RFC4408, section 3.1.3. However, this specific RFC only related to SPF-type TXT records, and not general validation records such as the one used for Google Site Verification.

I've illustrated the issue below:

$ dig franklaszlo.com txt +short
"google-site-verification=FNI0xUTGqcdI8YX" "xaPf_3mj33BYnNtY23ddD2Zl1ECc"
$ grep -C2 site-verification zones/f/franklaszlo.com 
; TXT RECORDS
@                   300   IN TXT   ( 
                                     "google-site-verification=FNI0xUTGqcdI8YX"
                                     "xaPf_3mj33BYnNtY23ddD2Zl1ECc"
                                   )

Screenshot 2023-07-21 at 10 31 59 AM

I'm not sure what the best fix here is, other than changing the split to be the max, 255 characters, for TXT records.

Let me know if you need further information

Invalid TTL and name when record name is numeric

In RFC1035 the structure of an entry is defined as:

    <domain-name><rr> [<comment>]
    <blank><rr> [<comment>]

If an entry for an RR begins with a blank, then the RR is assumed to be owned by the last stated owner. If an RR entry begins with a < domain-name >, then the owner name is reset.

<rr> contents take one of the following forms:
    [<TTL>] [<class>] <type> <RDATA>
    [<class>] [<TTL>] <type> <RDATA>

The RR begins with optional TTL and class fields, followed by a type and RDATA field appropriate to the type and class. Class and type use the standard mnemonics, TTL is a decimal integer. Omitted class and TTL values are default to the last explicitly stated values.

But when we pass an entry like 123 A 1.2.3.4 to the parser, it will consider that:

  • name is blank (so it's owned by the last stated owner)
  • TTL is 123

Where -based on RFC1035- it's expected to:

  • see 123 as name
  • use last stated or default TTL

Remove DNS Exception

There is no need for the DNSException, it doesn't do anything.
Need to implement existing exceptions

The content of a TXT record can be without quotes

In bind, as far as I know, it is allowed not to use quotes in TXT record. In Badcow\DNS\Parser\RdataHandlers::handleTxt the parsing stops when the content of the record does not start with a double quote.
Is it possible to fix this?
I use you package to parse bind files which live in DirectAdmin and there are a lot of zones with no quotes in the TXT record content.

Hopefully you can help me out.

DNSSEC

How add DNSSEC records?

Zone parse fails if RRSIG does not have host label

Parsing of zonefile fails with "Fatal error: Uncaught InvalidArgumentException:" if RRSIG record does not have host label. Following seems to be valid zone for named-checkzone:

poose.eu.		3600	IN SOA	ns.zone.eu. hostmaster.zone.eu. (
					2019122947 ; serial
					10800      ; refresh (3 hours)
					3600       ; retry (1 hour)
					2419200    ; expire (4 weeks)
					3600       ; minimum (1 hour)
					)
			3600	RRSIG	SOA 14 2 3600 (
					20200112073532 20191229133101 55179 poose.eu.
					utZQyR9wDynN8JE8DCVwYxix9eXpx45c4kDR
					ZqwzZnNVbz8UQv8Mt/AAqyqiKq4kHvGeczSp
					jj2fR8UIra3/eEowfeJzzPPuKmUsYO0WLuFy
					Ef8PJut23NefeEWo+1F7 )
			3600	NS	ns.zone.eu.
			3600	NS	ns2.zone.ee.
			3600	NS	ns3.zonedata.net.
			3600	RRSIG	NS 14 2 3600 (
					20200112073532 20191229133101 55179 poose.eu.
					bpGJmk6mA55QvkYejr33387hvWkg9z4pyhw4
					OLcw4NxTSVe8yna81Ey6jpbkkTTJxPBjo5fI
					kVNX3+12qG4fw4kswDzmzRvlTqXmujoLMbxx
					aAGW2YMATNJXM1d7PG77 )
			3600	A	217.146.69.44
			3600	RRSIG	A 14 2 3600 (
					20200112073532 20191229133101 55179 poose.eu.
					bDts/7a5qbal6s3ZYzS5puPSjEfys5yI6R/k
					prBBRDEfVcT6YwPaDT3VkVjKXdvpKX2/Dwpi
					jNAWkjpfsewCLmeImx3RgkzfuxfipRKtBUgu
					iPTBhkj/ft2halJziVXl )

RRSIG records appear to be interpreted as SOA, NS, A records when parsed as Badcow\DNS\Parser\Parser::parse( "poose.eu.", $zonefile )

Providing them with host label (or @) produces expected result.

And thanks for excellent library!

Road to 1.0

I'm happy with how this library is turning out. There is a great amount of flexibility for developers to implement the library in their own applications.

I feel as though there are some elements that are clunky and should be removed. I also think that some of the nomenclature needs to be reconsidered. As such, I will be working toward 1.0 with a mind of preserving backward compatibility from that version. Here are some of the things I'll be changing:

  • Remove the 'Rdata' part of the Rdata types. I.E. ARdata -> A, MxRdata -> MX
  • Send the AlignedBuilder to its own subpackage.
  • Remove the FormattableInterface as this will become part of the AlignedBuilder
  • Untie the validation from the zone objects. The Validator will remain (with a number of improvements) but the validation of individual properties will be removed from the methods and individual developers will validate the data before putting it into the object.
  • Add more RDATA types

Derived record name not supported

When parsing the attached example, a TLSA record named _25._tcp.example.com is not returned

_25._tcp.example.com. 43200 IN NSEC _443._tcp.example.com. RRSIG NSEC TLSA
43200 RRSIG NSEC 5 5 43200 (
20220306072900 20220204072900 23262 example.com.
aUbjBXyihDOA28Si5rBZ3OkV9QyzhnT5E3JT
/D30m1TPyJ1yTpo8mvY0jUclxfNnODN4ug49
9YI5UDjFLY1bjg== )
360 TLSA 3 1 1 (
01CA21026A705F21E7D0745849509B7C3F4D
F6862BC422475E0585E4C074A237 )
360 RRSIG TLSA 5 5 360 (
20220306072900 20220204072900 23262 example.com.
bTgf9yyfTe+Vcb/5AV73z42cZBXbLe0i+TOV
baol0gKslEWccsT68FwSaxKWdtKG+joWM6G6
4K2c0meRHONa8A== )

It appears 360 is parsed as the RR name

Documented here: https://stackoverflow.com/questions/70987780/hostnameless-records-in-zonefile

Misreading line as MX record

When working with the following bind file:

โžœ bug cat example.com.db 
$TTL 600
@       IN      SOA     ns1.example.com.      root.example.com. (
                                                2019081900
                                                600
                                                3600
                                                1209600
                                                86400 )

subdomain	888	IN	A	192.168.0.1
mx	900	IN	A	192.168.0.2

and the following script:

<?php

require __DIR__ . '/vendor/autoload.php';

use Badcow\DNS\Zone;

$file = file_get_contents("example.com.db");

$zoneToImport = Badcow\DNS\Parser\Parser::parse("example.com.", $file);

foreach ($zoneToImport->getResourceRecords() as $record) {
  var_dump($record);
}

The line mx 900 IN A 192.168.0.2 is read as MX record:

object(Badcow\DNS\ResourceRecord)#7 (5) {
  ["class":"Badcow\DNS\ResourceRecord":private]=>
  string(2) "IN"
  ["rdata":"Badcow\DNS\ResourceRecord":private]=>
  object(Badcow\DNS\Rdata\A)#8 (1) {
    ["address":protected]=>
    string(11) "192.168.0.1"
  }
  ["ttl":"Badcow\DNS\ResourceRecord":private]=>
  int(888)
  ["name":"Badcow\DNS\ResourceRecord":private]=>
  string(9) "subdomain"
  ["comment":"Badcow\DNS\ResourceRecord":private]=>
  NULL
}
object(Badcow\DNS\ResourceRecord)#9 (5) {
  ["class":"Badcow\DNS\ResourceRecord":private]=>
  NULL
  ["rdata":"Badcow\DNS\ResourceRecord":private]=>
  object(Badcow\DNS\Rdata\MX)#10 (2) {
    ["preference":"Badcow\DNS\Rdata\MX":private]=>
    int(900)
    ["exchange":"Badcow\DNS\Rdata\MX":private]=>
    string(2) "IN"
  }
  ["ttl":"Badcow\DNS\ResourceRecord":private]=>
  NULL
  ["name":"Badcow\DNS\ResourceRecord":private]=>
  string(9) "subdomain"
  ["comment":"Badcow\DNS\ResourceRecord":private]=>
  NULL
}

When changing the name of the subdomain to mxs, it works as intended.

lastStatedTtl Handling

Hi!

Is it possible to disable the lastStatedTtl handling? In our setup, all records get a TTL if one record has a TTL set.

Thanks!

Support for reverse zones

Currently there is no PTR RR implementation and Validator::validateFqdn method doesn't properly validate reverse zone names.

Using , as domain name should reset last stated domain

In RFC1035 (section 5), it's mentioned that:

If an entry for an RR begins with a blank, then the RR is assumed to be owned by the last stated owner. If an RR entry begins with a , then the owner name is reset.

But the parser doesn't behave like this.

Invalid records on creation and parsing

I can create invalid records with this library and am not able to parse zonefiles with invalid records (e.g. skip invalid records).

Test script:

<?php


declare(strict_types = 1);


use Badcow\DNS\Parser\Parser;
use Badcow\DNS\Rdata\MX;
use Badcow\DNS\ResourceRecord;
use Badcow\DNS\Zone;
use Badcow\DNS\ZoneBuilder;


require __DIR__."/../vendor/autoload.php";

// create zone
$z  = new Zone( "example.org" );
$mx = new MX();
$mx->setExchange( "foo" );
$r = new ResourceRecord( "foo", $mx );
$z->addResourceRecord( $r );
$zone = ZoneBuilder::build( $z );
echo "$zone\n\n\n";

// parse created zone
$parsedZone = Parser::parse( "example.org", $zone );
$pz         = ZoneBuilder::build( $parsedZone );
echo "$pz\n\n\n";

Output:

// create zone
$ORIGIN example.org
foo MX foo // invalid



// parse created zone
Fatal error: Uncaught ArgumentCountError: Too few arguments to function Badcow\DNS\Rdata\Factory::Mx(), 1 passed and exactly 2 expected in vendor/badcow/dns/lib/Rdata/Factory.php:125
Stack trace:
#0 [internal function]: Badcow\DNS\Rdata\Factory::Mx('foo')
#1 vendor/badcow/dns/lib/Parser/RdataHandlers.php(147): call_user_func_array(Array, Array)
#2 vendor/badcow/dns/lib/Parser/Parser.php(224): Badcow\DNS\Parser\RdataHandlers::catchAll('MX', Object(ArrayIterator))
#3 vendor/badcow/dns/lib/Parser/Parser.php(106): Badcow\DNS\Parser\Parser->extractRdata(Object(ArrayIterator))
#4 vendor/badcow/dns/lib/Parser/Parser.php(80): Badcow\DNS\Parser\Parser->processLine('foo MX foo')
#5 vendor/badcow/dns/lib/Parser/Parser.php(63): Badcow\DNS\Parser\Parser->makeZone('example.org', '$ORIGIN example...')
#6 bin/test.php(24): Badcow\DNS\Parser\Parser::parse('example.or in vendor/badcow/dns/lib/Rdata/Factory.php on line 125

This should be handled by the library of not beeing able to create invalid data.

Parser: TXT record with number as value throws exception

Reproduce:

<?php

require_once 'vendor/autoload.php';

$zone = Badcow\DNS\Parser\Parser::parse('foo.tld.', 'foo.	14400	IN	TXT	3600');

stack trace:

PHP Fatal error:  Uncaught TypeError: Argument 1 passed to Badcow\DNS\Classes::isValid() must be of the type string, null given, called in /path/to/project/vendor/badcow/dns/lib/Parser/Parser.php on line 365 and defined in /path/to/project/vendor/badcow/dns/lib/Classes.php:53
Stack trace:
#0 /path/to/project/vendor/badcow/dns/lib/Parser/Parser.php(365): Badcow\DNS\Classes::isValid(NULL)
#1 /path/to/project/vendor/badcow/dns/lib/Parser/Parser.php(415): Badcow\DNS\Parser\Parser->isClass(Object(Badcow\DNS\Parser\ResourceRecordIterator), 'TTL')
#2 /path/to/project/vendor/badcow/dns/lib/Parser/Parser.php(342): Badcow\DNS\Parser\Parser->isTTL(Object(Badcow\DNS\Parser\ResourceRecordIterator))
#3 /path/to/project/vendor/badcow/dns/lib/Parser/Parser.php(170): Badcow\DNS\Parser\Parser->isResourceName(Object(Badcow\DNS\Parser\ResourceRecordIterator))
#4 /path/to/project/vendor/badcow/dns/lib/Parser/P in /path/to/project/vendor/badcow/dns/lib/Classes.php on line 53

(Might be related to #88 ?)

Thank you for maintaining this library, it's a real ๐Ÿ’Ž!

Example output AlignedBuilder not setting class (IN)

When executing the example code with the AlignedBuilder all the lines in the outputhad the class set to IN. When executing the same code the class is not set.

$ORIGIN example.com.
$TTL 3600
@               SOA  (
                     example.com.      ; MNAME
                     post.example.com. ; RNAME
                     2014110501        ; SERIAL
                     3600              ; REFRESH
                     14400             ; RETRY
                     604800            ; EXPIRE
                     3600              ; MINIMUM
                     )

; NS RECORDS
@               NS   ns1.nameserver.com.
@               NS   ns2.nameserver.com.

; A RECORDS
sub.domain      A    192.168.1.42; This is a local ip.

; AAAA RECORDS
ipv6.domain     AAAA ::1; This is an IPv6 domain.

; MX RECORDS
@               MX   10 mail-gw1.example.net.
@               MX   20 mail-gw2.example.net.
@               MX   30 mail-gw3.example.net.

; LOC RECORDS
canberra        LOC  (
                     35 18 27.000 S ; LATITUDE
                     149 7 27.840 E ; LONGITUDE
                     500.00m        ; ALTITUDE
                     20.12m         ; SIZE
                     200.30m        ; HORIZONTAL PRECISION
                     300.10m        ; VERTICAL PRECISION
                     ); This is Canberra

RRSIG records aren't process correctly

Hi,

The following record isn't processed

RRSIG	SOA 8 2 86400 (
		20200416000000 20200326000000 25078 3mtape.nl.
		sLGSfcmcvXQ4EGMXrUFFE1JO17AxhspZY8xXiCLEDN95
		S90KgnDUKzzIUTjjGao0G7XpzhoCgsXyAyJeTgTwa4v5
		ICV8xCF1dpUMb7aHRw2l0MA2dDZ30w33QTqU7TEbETpy
		NqTbK9qaabsTTXSIGg2ChKV8MwiGm/TyjnARjVo= )

This is due to that the iterator isn't at the beginning on the line below :

$this->currentResourceRecord->setRdata($this->extractRdata($iterator));

The solution would be to implement it as follows

if ($this->isType($iterator)) {
    while ($iterator->key() > 1 && $this->isType($iterator)) {
        $iterator->prev();
    }
    $iterator->next();

    $this->currentResourceRecord->setRdata($this->extractRdata($iterator));
    $this->populateWithLastStated();

    return;
}

AlignedBuilder needs finer controls

Change AlignedBuilder around so that you can have some finer control on how things are done. As I said before, AlignedBuilder is designed around my arbitrary opinions, but it would be good if developers can add their own specialised handlers into the builder. This would be a BC-breaking change, but can be shipped with v4. I envisaged something like:

function myTxtHandler(Rdata\TXT $txt): string {
     //return text that is cut down into smaller chunks.
}

$builder = new AlignedBuilder();
                        //(string $type,  callable $renderer)
$builder->setRdataRenderer('TXT', 'myTxtHandler');

Originally posting in PR #83

Inconsistent handling of signatures, keys, etc.

The handling of cryptographic keys, signatures and other data that is ultimately represented as Base16, 32, or 64 encoded string is inconsistent across all Rdata type classes. These should be handled the same.

Signatures et al inputted into Rdata classes SHOULD be setted and getted in raw binary form; the only time it is outputted to a text encoding is when $rdata->toText() is called.

This would be a backward-compatibility breaking change, so will not be implemented until v4.0

These are the classes that are affected:

  • KEY
    • DNSKEY
      • CDNSKEY
  • DS
    • CDS
    • DLV
    • TA
  • CERT
  • DHCID
  • HIP
  • IPSECKEY
  • NSEC3
  • RRSIG
    • SIG
  • SSHFP
  • TKEY
  • TLSA
  • TSIG

The future code should look like:

$rdata = new TYPE1234();
$rdata->setPublicKey(10100011110000111010101110001001...);
$rdata->getPublicKey(); // Returns 10100011110000111010101110001001...
echo $rdata->toText(); // Echos o8OriQ...

The downside of this would be that you would need to be careful to decode already Base64 encoded strings.

How to use this lib with Laravel

Hi,

I'm developing a DNS Management app with Laravel. I'd like to use your lib in order to deal with DNS records. This will improve resource record validation and get a more ordered way to design my app structure.

But I don't know how to use your lib with Eloquent / Model model. I suppose I can extend Model with your Rdata models, but I don't know It's the best way.

For example: When an user submit a new record form, We don't know what Rdata to use... I suppose I can use a switch case for each one, Isn't it?

Thanks in advance.

domainname/hostname validation with _

Hi,

When parsing records like this

$ORIGIN _domainkey.mydomain.at.
XXXXXXXXXXl 3600 CNAME XXXXXXXX.dkim.amazonses.com.

I got this exceptions

Zone "_domainkey.mydomain.at." is not a fully qualified domain name.

I think this is related to #65 (domainanme vs. hostname).

Best,
Michael

Wildcards not supported

$wc->setName('*');

The name is not a Fully Qualified Domain Name in Badcow\DNS\ResourceRecord->setName() (line 71 of ---/badcow/dns/lib/ResourceRecord.php).

Is this not supported by the RFC?

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.