/* Sockme.c -- Windows sockets sample application */ /*% cl sockme.c wsock32.lib */ #include #include #include #include char *note[]= { "Usage: [Options] URL", "Print the URL (HTTP access only)", "URL may be of the form username:password@host/page.html", "Options:", "-h Just get the headers [HEAD instead of GET]", "-x file POST file to the URL", "-s fname Save return as file fname [print headers on console]", "-p proxy:port Use a proxy with the given port", "-a fname Add the contents of file fname to the header being sent", "-v Verbose", 0}; /* Global buffers */ char buff[2048]; char ahost[256]; char *outname; struct sockaddr_in anaddr; u_short httpport= 80; /* Port for http */ int app_closing; WSADATA wskData; struct hostent *hp; /* Sockets */ SOCKET fclient = INVALID_SOCKET; void errormsg(char *msg){ int err= WSAGetLastError(); if(msg) fprintf(stderr, "%s [%d]\n", msg, err); /* Close any open sockets */ if(fclient != INVALID_SOCKET) closesocket(fclient); /* Let windows sockets know we're done */ WSACleanup(); exit(msg? 5:0); } static char *encode(char *outstg, char *stg){ /* Base64 encoding without CRLF every 64 (or 72) characters-- * (just for a short string) * Note--out must be 4/3 longer than stg */ int i, n; unsigned char igroup[3]; unsigned char dtable[64]; char *cp= outstg; /* Fill dtable with character encodings. */ for(i= 0; i < 26; i++){ dtable[i]= 'A' + i; dtable[26 + i]= 'a' + i; } for(i= 0; i < 10; i++){ dtable[52 + i]= '0' + i; } dtable[62]= '+'; dtable[63]= '/'; while(*stg){ igroup[0]= 0; igroup[1]= 0; igroup[2]= 0; for(n= 0; n<3 && *stg; n++) igroup[n]= *stg++; cp[0]= dtable[igroup[0] >> 2]; cp[1]= dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)]; cp[2]= dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)]; cp[3]= dtable[igroup[2] & 0x3F]; /* Replace characters in output stream with "=" pad * characters if fewer than three characters were read * from the end of the input stream. */ while(n<3) cp[++n]= '='; cp += 4; } *cp= 0; return outstg; } void do_send(SOCKET s, char *buff, int nb){ while(nb>0){ int cnt= send(s, buff, nb, 0); if(cnt == SOCKET_ERROR) errormsg("Error sending string to http daemon"); nb -= cnt; buff += cnt; } } void main(int ac, char **av){ FILE *fpout= stdout; FILE *fppost= 0; FILE *fp; int ntot= 0; int cnt; char *command= "GET"; char *proxy= 0; char *host= ahost; char *url= 0; char *user= 0; int verbose= 0; char *headextra; char *poster= 0; char *bufp; unsigned long lAddr; while(*++av)if(**av=='-')switch(av[0][1]){ case 'x': poster= *++av; command= "POST"; break; case 'a': headextra= *++av; break; case 'v': verbose= 1; break; case 'h': command= "HEAD"; break; case 's': outname= *++av; break; case 'p': proxy= *++av; break; default: err: for(av= note; *av; ++av) fprintf(stderr, "%s\n", *av); exit(5); }else if(!url) url= *av; else goto err; if(!url) goto err; if(command[0]=='H') /* No output file with the HEAD command */ outname= 0; _setmode(1, _O_BINARY); /* May not be receiving text */ if(proxy){ strcpy(host, proxy); }else{ if(!strnicmp(url, "HTTP://", 7)) url += 7; strcpy(host, url); if(bufp= strchr(host, '/')){ url= bufp; *url= 0; }else url= "/"; } /* Check for user:password@host */ if(bufp= strchr(host, '@')){ user= host; *bufp++= 0; host= bufp; } if(bufp= strchr(host, ':')){ *bufp++= 0; httpport= atoi(bufp); } if(WSAStartup(MAKEWORD(2,0), &wskData)) return; /* Try numeric ip, then lookup host name */ lAddr= inet_addr(host); if(lAddr == INADDR_NONE){ if((hp = gethostbyname(host)) == NULL) errormsg("Unknown host"); memcpy((char *) &anaddr.sin_addr.s_addr, hp->h_addr, hp->h_length); }else memcpy((char *) &anaddr.sin_addr.s_addr, &lAddr, sizeof(lAddr)); /* Look up port number (this seems to fail for http) */ if(httpport == 0){ struct servent *sp; if((sp= getservbyname("http", NULL)) == NULL) errormsg("Cannot determine port number for http daemon."); httpport = htons(sp->s_port); } /* Create socket */ if((fclient= socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) errormsg("Unable to create a socket"); /* Fill in address to which we will connect */ anaddr.sin_family = PF_INET; anaddr.sin_port = htons(httpport); /* Try to connect */ if(connect(fclient, (struct sockaddr *)&anaddr, sizeof(struct sockaddr_in))) errormsg("Unable to connect to http daemon."); if(verbose) printf("...Connected to%s%s:%d\n", proxy? " proxy ":" ", host, httpport); /* Now construct the header to send */ bufp= buff; if(!proxy) *url= '/'; sprintf(bufp, "%s %s HTTP/1.0\r\n", command, url); bufp += strlen(bufp); if(user){ /* Add basic authentication: * Authorization: Basic [user:password,base64 encoded] * or Proxy-Authorization: Basic [user:password,base64 encoded] */ sprintf(bufp, "%s: Basic %s\r\n", proxy? "Proxy-Authorization":"Authorization", encode(&buff[1000], user)); bufp += strlen(bufp); } /* Posting a file? -- Put the length in the header */ if(poster && (fppost= fopen(poster, "rb"))){ /* Get ntot= length of file to post */ fseek(fppost, 0, SEEK_END); ntot= ftell(fppost); fseek(fppost, 0, SEEK_SET); sprintf(bufp, "Content-Length: %d\r\n", ntot); bufp += strlen(bufp); } /* Send more header stuff */ if(headextra && (fp= fopen(headextra, "rt"))){ cnt= &buff[sizeof(buff)] - bufp; while(cnt>128 && fgets(bufp, cnt, fp)){ int k= strlen(bufp); if(k>1){ bufp += k+1; strcpy(bufp-2, "\r\n"); cnt -= k; } } fclose(fp); } strcpy(bufp, "\r\n"); bufp += 2; if(verbose) printf("...Sending:\n%s", buff); do_send(fclient, buff, bufp-buff); if(fppost){ if(verbose) printf("...posting %d bytes\n", ntot); while(ntot>0){ /* Read a buffer-full of the file to post */ cnt= fread(buff, 1, ntot0 || cnt==SOCKET_ERROR); fclose(fpout); errormsg(NULL); }