C (+ prises), 433 429 280 276 270 259 octets
#define H"medalbot.com"
char**p,B[999],*b=B;main(f){connect(f=socket(2,1,getaddrinfo("www."H,"80",0,&p)),p[4],16);send(f,"GET http://"H"/api/v1/medals HTTP/1.1\r\nHost:"H"\r\n\r\n",69);read(f,b,998);for(f=3;f--;puts(p))b=strchr(p=strstr(++b,"_n")+9,34),*b=0;}
Il s'avère donc que C n'est pas génial pour télécharger des ressources à partir d'Internet et les analyser en JSON. Qui savait?
Ce code est (naturellement) super laxiste avec vérification des erreurs, donc je suppose que si medalbot.com voulait envoyer des données malveillantes, il serait capable de déclencher des dépassements de tampon, etc. De plus, le dernier code attend certaines valeurs pour les constantes (par exemple AF_INET = 2
) qui sera probablement le cas partout, mais ce n'est pas garanti.
Voici le code original qui n'est pas si fragile (mais qui n'est toujours pas très robuste ou sûr):
#include<netdb.h>
#define H"medalbot.com"
char*b,*B,d[999];struct addrinfo*p,h;main(f){h.ai_socktype=SOCK_STREAM;getaddrinfo("www."H,"80",&h,&p);f=socket(p->ai_family,p->ai_socktype,p->ai_protocol);connect(f,p->ai_addr,p->ai_addrlen);send(f,"GET http://"H"/api/v1/medals HTTP/1.1\r\nHost: "H":80\r\nConnection: close\r\n\r\n",92,0);recv(f,d,998,0);for(f=0,b=d;f<3;++f)B=strstr(b,"_n")+9,b=strchr(B,'}'),*strchr(B,'"')=0,puts(B);}
Panne:
// No imports needed whatsoever!
#define H"medalbot.com" // Re-use the host in multiple places
char**p, // This is actually a "struct addrinfo*"
B[999], // The download buffer (global to init with 0)
*b=B; // A mutable pointer to the buffer
main(f){
// Hope for the best: try the first suggested address with no fallback:
// (medalbot.com runs on Heroku which has dynamic IPs, so we must look up the
// IP each time using getaddrinfo)
f=socket(2,1,getaddrinfo("www."H,"80",0,&p));
// 2 = AF_INET
// 1 = SOCK_STREAM
// (may not match getaddrinfo, but works anyway)
// 0 = IP protocol (getaddrinfo returns 0 on success)
connect(f,p[4],16); // struct addrinfo contains a "struct sockaddr" pointer
// which is aligned at 32 bytes (4*8)
// Send the HTTP request (not quite standard, but works. 69 bytes long)
send(f,"GET http://"H"/api/v1/medals HTTP/1.1\r\nHost:"H"\r\n\r\n",69);
// (omit flags arg in send and hope 0 will be assumed)
read(f,b,998); // Get first 998 bytes of response; same as recv(...,0)
// Loop through the top 3 & print country names:
// (p is re-used as a char* now)
for(f=3;f--;puts(p)) // Loop and print:
p=strstr(++b,"_n")+9, // Find "country_name": "
b=strchr(p,34), // Jump to closing "
*b=0; // Set the closing " to \0
}
Ce n'est pas très agréable pour le serveur car nous n'envoyons pas Connection: close\r\n
dans le cadre de la requête HTTP. Il omet également l'en- Accept
tête, car medalbot.com ne semble en aucun cas utiliser la compression et manque l'espace après Host:
(encore une fois, le serveur semble être d'accord avec cela). Il ne semble pas que quelque chose d'autre puisse être supprimé.
Une fois les Jeux Olympiques terminés, le comportement le plus probable de ce programme consiste à segfault en essayant de lire l'emplacement de la mémoire 9. À moins qu'un pirate malveillant ne prenne le contrôle du domaine, auquel cas le comportement le plus probable consiste à définir un octet à 0 dans l'adresse structs info, ce qui n'est probablement pas trop dangereux en fait. Mais qui peut dire avec ces pirates maléfiques?