#include #include #include #include #include #include #include #include #define MAX_RECURS 5 #include "web.h" char lastcontenttype[256]; /* init_sockaddr : some stuff....! */ int init_sockaddr (struct sockaddr_in * name, const char * hostname, unsigned short int port) { struct hostent * hostinfo; name -> sin_family = AF_INET; name -> sin_port = htons (port); hostinfo = gethostbyname (hostname); if (hostinfo == NULL) { fprintf (stderr, "Unknown host (%s)\n", hostname); return 1; } name -> sin_addr = * (struct in_addr *)hostinfo -> h_addr; return 0; } void remove_end_crap(char * s) { char * p = s; while (*p) p++; while (--p >= s) { if (*p == '\n' || *p == '\r') *p = 0; else return; } } sig_atomic_t alarmoccured = 0; void alarmhandler(int sig) { alarmoccured = 1; } FILE * Download (char * pszHost, int nPort, char * pszFile, char * pszDest, int level, int bOverwrite) { struct sockaddr_in socketaddr; int hSocket, bInHeader; char szRequest [512]; char szLine[256]; int i, l; int eof = 0; FILE * fp = NULL; int bGotContenttype = 0; alarmoccured = 0; if (level == 0) { if (options.bVerbose) printf("%s:%d/%s ", pszHost, nPort, pszFile); fflush(stdout); } else if (level > MAX_RECURS) { printf("Too many redirects\n"); return NULL; } if (!bOverwrite && file_exists(pszDest, pszHost, nPort, pszFile)) { if (options.bVerbose) printf("exists\n"); return NULL; } hSocket = socket (PF_INET, SOCK_STREAM, 0); if (hSocket < 0) { printf("SOCKET FAILED\n"); return NULL; } if (init_sockaddr (&socketaddr, pszHost, nPort)) return NULL; if (options.timeout != 0) { signal(SIGALRM, alarmhandler); alarm(options.timeout); } if (connect (hSocket, (struct sockaddr *)&socketaddr, sizeof (socketaddr))) { printf("CONNECT FAILED\n"); return NULL; } if (options.timeout && options.bNoDataTO) { alarm(options.timeout); } snprintf (szRequest, 512, "GET http://%s/%s HTTP/1.0\n", pszHost, pszFile); strcat (szRequest, "User-Agent: "); strcat (szRequest, options.userAgent); strcat (szRequest, "\n\n"); write (hSocket, szRequest, strlen (szRequest) ); if (options.timeout && options.bNoDataTO) { alarm(options.timeout); } bInHeader = 1; strcpy(lastcontenttype, "text/plain"); /* default content type */ while (! eof) { l = 0; while (l < 255 && ! eof) { if (! read(hSocket, & (szLine[l]), 1)) eof = 1; else if (szLine[l++] == '\n') break; if (alarmoccured) { if (options.bVerbose) printf ("TIMEOUT\n"); close(hSocket); if (bInHeader) /* no data */ { fclose(fp); return NULL; } return fp; } if (options.timeout && options.bNoDataTO) { alarm(options.timeout); } } szLine[l] = '\0'; /* Need to recognised 'HTTP/xxx nnn status' line at start of header */ if (bInHeader) /* in the header */ { if (! strcmp (szLine,"\r\n")) /* line empty => end of header */ { /* needs modification to support If-Modified-Since? */ bInHeader = 0; pszFile = rename_object(pszHost, nPort, pszFile, bGotContenttype ? lastcontenttype : "application/x-unknown"); fp = CreateFile(pszDest, pszHost, nPort, pszFile, bOverwrite); if (! fp) { alarm(0); printf("COULDN'T CREATE\n"); close(hSocket); return NULL; } } else if (! strncmp(szLine, "Location: ", 10)) { SplitURL (& (szLine[17]), pszHost, pszFile, &nPort); close(hSocket); if (options.bVerbose) printf("-> %s:%d/%s ", pszHost, nPort, pszFile); fflush(stdout); /* need to consider creating a symlink to new location */ alarm(0); return Download(pszHost, nPort, pszFile, pszDest, level + 1, bOverwrite); } else if (! strncmp(szLine, "Content-Type: ", 14) || ! strncmp(szLine, "Content-type: ", 14)) { strcpy(lastcontenttype, & (szLine[14])); remove_end_crap(lastcontenttype); bGotContenttype = 1; } /* ignore any other header lines... */ continue; } else /* in body of file */ { for (i = 0; i < l; i++) fputc(szLine[i], fp); } } close(hSocket); alarm(0); if (bInHeader) { printf("NO DATA\n"); fclose(fp); return NULL; } if (options.bVerbose) printf("OK\n"); return fp; }