// Erica Sadun, 24 March 2008
//
// cc panda.c -w -lcurl -o panda
//

#include 
#include 
#include 
#include 
#include 
#include 

#define ITMSSITE "phobos.apple.com"
#define SLEN 4096
#define MLEN 50000

main(argc, argv)
int argc;
char **argv;
{
    char headertext[SLEN], mtext[MLEN];
    char *c;
    int riz, i;

    if (argc < 2) {
        printf("usage: %s # | gunzip\n", argv[0]);
        printf("1: view panda updates\n");
        printf("2: top 50\n");
        printf("3: featured genres\n");
        printf("4: view panda storefront\n");
        printf("5: top tens\n");
        exit(0);
    }

    int whichRequest = atoi(argv[1]);
    if ((whichRequest < 1) || (whichRequest > 5)) {
       printf("Error: request must be within 1-5\n");
       exit(-1);
    }

    // Create Headers

    if (whichRequest == 1)
      sprintf(headertext, "GET /WebObjects/MZStore.woa/wa/viewPandaUpdates HTTP/1.1\n");
    else if (whichRequest == 2)
      sprintf(headertext, "GET /WebObjects/MZStore.woa/wa/viewTopFifty HTTP/1.1\n");
    else if (whichRequest == 3)
      sprintf(headertext, "GET /WebObjects/MZStore.woa/wa/viewFeaturedGenres HTTP/1.1\n");
    else if (whichRequest == 4)
      sprintf(headertext, "GET /WebObjects/MZStore.woa/wa/pandaStoreFront HTTP/1.1\n");
    else if (whichRequest == 5)
      sprintf(headertext, "GET /WebObjects/MZStore.woa/wa/viewTopTensList HTTP/1.1\n");

    #define IPHONE12 "iTunes-iPhone/1.2.0"
    sprintf(headertext, "%sUser-Agent: %s\n", headertext, IPHONE12);

    sprintf(headertext, "%sAccept-Language: en-us, en;q=1.0\n", headertext);
    sprintf(headertext, "%sX-Apple-Store-Front: 143441-1,2\n", headertext);
    sprintf(headertext, "%sCookie: countryVerified=1\n", headertext);
    sprintf(headertext, "%sAccept-Encoding: gzip, x-aes-cbc\n", headertext);
    sprintf(headertext, "%sConnection: close\n", headertext);
    sprintf(headertext, "%sHost: phobos.apple.com\n", headertext);

    sprintf(headertext, "%s\n", headertext);

    // Send the message
    if ((riz = dosend(headertext, mtext)) == 0)
    {
        printf("Could not connect properly. Sorry.\n");
        exit(1);
    }

   // skip header & output results
   for (i = 0; (!((mtext[i] == '\n') && (mtext[i+2] == '\n'))); i++) ;
   i += 3;
   for (i; i < riz; i++) printf("%c", mtext[i]);
}

int dosend(s, mtext)
char *s, *mtext;
{
    struct hostent *hp;
    struct sockaddr_in sin;
    struct msghdr *msg;
    char buff[4096];
    int sd, i, offset;
    int ngot, flags;

    if ((hp = gethostbyname(ITMSSITE)) == 0)
    {
       printf("Could not attach to host %s.  Try again later.\n", 
	ITMSSITE); exit(-1);
    }

    /* Host Received */  
    bzero(&sin, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;
    sin.sin_port = htons(80);
    if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
    {
      printf("Socket failed\n"); exit(-1);
    }

    /* Perform Connection */  
    if (connect(sd, (const struct sockaddr *) &sin, sizeof(sin)) == -1) 
        {printf("Connection Error\n"); close(sd); return 0;}

    /* Send Request */
    if ((ngot = send(sd, s, strlen(s), 0)) < 0)
    {printf("Could not send msg\n"); return 0;}

    /* Retrieve Results */
    sprintf(mtext, ""); offset = 0;
    while ((ngot = recv(sd, buff, 4096, 0)) > 0)
    {
       for (i = 0; i < ngot; i++) mtext[offset+i] = buff[i];
       offset += ngot;
    }

    /* Tidy up */
    close(sd);
    return offset;	
}