C (+ Sockets): 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;}
Es stellt sich also heraus, dass C nicht gut darin ist, Ressourcen aus dem Internet herunterzuladen und sie als JSON zu analysieren. Wer wusste?
Dieser Code ist (natürlich) sehr lasch bei der Fehlerprüfung. Wenn medalbot.com also bösartige Daten senden möchte, können sie möglicherweise Pufferüberläufe auslösen. Auch der neueste Code erwartet bestimmte Werte für die Konstanten (z. B. AF_INET = 2
), die wird wahrscheinlich überall der Fall sein, aber es ist nicht garantiert.
Hier ist der Originalcode, der nicht so zerbrechlich ist (aber immer noch nicht sehr robust oder sicher ist):
#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);}
Nervenzusammenbruch:
// 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
}
Dies ist für den Server nicht sehr hilfreich, da wir nicht Connection: close\r\n
als Teil der HTTP-Anforderung senden . Der Accept
Header wird ebenfalls weggelassen, da medalbot.com in keinem Fall die Komprimierung zu verwenden scheint und das Leerzeichen danach fehlt Host:
(auch hier scheint der Server damit einverstanden zu sein). Es scheint jedoch nicht, dass etwas anderes entfernt werden kann.
Sobald die Olympischen Spiele zu Ende sind, versucht dieses Programm am wahrscheinlichsten, den Speicherort 9 auszulesen. In diesem Fall ist es am wahrscheinlichsten, dass ein Byte in der Adresse auf 0 gesetzt wird, es sei denn, ein böser Hacker übernimmt die Domäne info structs, was eigentlich wahrscheinlich nicht allzu gefährlich ist. Aber wer kann es mit diesen bösen Hackern sagen?