C (+ socket), 433 429 280 276 270 259 byte
#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;}
Quindi si scopre che C non è eccezionale nel scaricare risorse da Internet e analizzarle come JSON. Chi lo sapeva?
Questo codice è (naturalmente) super lassista con il controllo degli errori, quindi immagino che se medalbot.com volesse inviare dati dannosi sarebbero in grado di innescare overflow del buffer, ecc. Anche l'ultimo codice prevede determinati valori per le costanti (ad es. AF_INET = 2
) Che sarà probabilmente il caso ovunque, ma non è garantito.
Ecco il codice originale che non è così fragile (ma non è ancora molto robusto o sicuro):
#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);}
Abbattersi:
// 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
}
Questo non è molto utile per il server poiché non inviamo Connection: close\r\n
come parte della richiesta HTTP. Accept
Omette anche l' intestazione poiché medalbot.com non sembra utilizzare la compressione in ogni caso e perde lo spazio dopo Host:
(di nuovo, il server sembra essere OK con questo). Non sembra che sia possibile rimuovere qualsiasi altra cosa.
Una volta terminate le olimpiadi, il comportamento più probabile per questo programma è quello di segfault nel tentativo di leggere la posizione di memoria 9. A meno che un hacker malvagio prenda il dominio, nel qual caso il comportamento più probabile è quello di impostare un byte su 0 nell'indirizzo strutture informative, che probabilmente non sono troppo pericolose in realtà. Ma chi può dirlo con questi hacker malvagi?