// From Erica Sadun, 14 April 2006 
// Updated 30 May 2006 to add the store option
//
// cc fetchalbum.c -w -lcurl -o fetchalbum -lcurl
//
// Sample Usage: 
// ./fetchalbum 140812843 | gunzip | xmllint --format - | open -f
//
// Use a second argument to fetch album text from a specific store.


#include <stdio.h>#include <stdlib.h>#include <sys/socket.h>
#include <string.h>#include <netdb.h>
#include <curl/curl.h>

#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 albumid | gunzip\n", argv[0]);
        exit(-1);
    }

    // Create Headers   
    sprintf(headertext, "GET /WebObjects/MZStore.woa/wa/com.apple.jingle.app.store.DirectAction/viewAlbum?id=%s HTTP/1.1\n", argv[1]);
    sprintf(headertext, "%sUser-Agent: iTunes/4.2 (Macintosh; U; PPC Mac OS X 10.2)\n", headertext);
    sprintf(headertext, "%sAccept-Language: en-us, en;q=0.50\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);

    if (argc > 2)
    {
      sprintf(headertext, "%sX-Apple-Store-Front: %s-1\n", 
        headertext, argv[2]);
    }

    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;	
}
