186883Smatusita/* 286883Smatusita * Copyright (c) 1999 386883Smatusita * Philipp Mergenthaler <philipp.mergenthaler@stud.uni-karlsruhe.de> 486883Smatusita * All rights reserved. 586883Smatusita * 686883Smatusita * Redistribution and use in source and binary forms, with or without 786883Smatusita * modification, are permitted provided that the following conditions 886883Smatusita * are met: 986883Smatusita * 1. Redistributions of source code must retain the above copyright 1086883Smatusita * notice, this list of conditions and the following disclaimer. 1186883Smatusita * 2. Redistributions in binary form must reproduce the above copyright 1286883Smatusita * notice, this list of conditions and the following disclaimer in the 1386883Smatusita * documentation and/or other materials provided with the distribution. 1486883Smatusita * 1586883Smatusita * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1686883Smatusita * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1786883Smatusita * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1886883Smatusita * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1986883Smatusita * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2086883Smatusita * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2186883Smatusita * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 2286883Smatusita * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2386883Smatusita * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2486883Smatusita * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2586883Smatusita * SUCH DAMAGE. 2686883Smatusita * 2786883Smatusita * $FreeBSD$ 2886883Smatusita */ 2986883Smatusita 3055393Sjkh#include "sysinstall.h" 3155393Sjkh#include <sys/socket.h> 3255393Sjkh#include <netinet/in.h> 3355393Sjkh#include <arpa/inet.h> 3455393Sjkh#include <sys/param.h> 3555393Sjkh#include <netdb.h> 3655393Sjkh 3769647Sjkhextern const char *ftp_dirs[]; /* defined in ftp.c */ 3869647Sjkh 39248313SdteskeBoolean 40248313SdteskecheckAccess(Boolean connectCheckOnly, Boolean isProxy) 4155393Sjkh{ 4263118Sume int rv, s, af; 4366369Sjkh bool el, found=FALSE; /* end of header line */ 4469647Sjkh char *cp, buf[PATH_MAX], req[BUFSIZ]; 4563118Sume struct addrinfo hints, *res, *res0; 4655393Sjkh 4763118Sume af = variable_cmp(VAR_IPV6_ENABLE, "YES") ? AF_INET : AF_UNSPEC; 4863118Sume memset(&hints, 0, sizeof(hints)); 4963118Sume hints.ai_family = af; 5063118Sume hints.ai_socktype = SOCK_STREAM; 5163118Sume hints.ai_protocol = 0; 5263118Sume if ((rv = getaddrinfo(variable_get(VAR_HTTP_HOST), 5363118Sume variable_get(VAR_HTTP_PORT), &hints, &res0)) != 0) { 5463118Sume msgConfirm("%s", gai_strerror(rv)); 5569647Sjkh variable_unset(VAR_HTTP_HOST); 5656573Sjkh return FALSE; 5755393Sjkh } 5863118Sume s = -1; 5963118Sume for (res = res0; res; res = res->ai_next) { 6063118Sume if ((s = socket(res->ai_family, res->ai_socktype, 6163118Sume res->ai_protocol)) < 0) 6263118Sume continue; 6363118Sume if (connect(s, res->ai_addr, res->ai_addrlen) >= 0) 6463118Sume break; 6563118Sume close(s); 6663118Sume s = -1; 6755393Sjkh } 6863118Sume freeaddrinfo(res0); 6963118Sume if (s == -1) { 70248313Sdteske if (isProxy) { 71248313Sdteske msgConfirm("Couldn't connect to proxy %s:%s", 72248313Sdteske variable_get(VAR_HTTP_HOST),variable_get(VAR_HTTP_PORT)); 73248313Sdteske } else { 74248313Sdteske msgConfirm("Couldn't connect to server http://%s:%s/", 75248313Sdteske variable_get(VAR_HTTP_HOST),variable_get(VAR_HTTP_PORT)); 76248313Sdteske } 7769647Sjkh variable_unset(VAR_HTTP_HOST); 7856573Sjkh return FALSE; 7955393Sjkh } 80248313Sdteske if (connectCheckOnly) { 8169647Sjkh close(s); 8269647Sjkh return TRUE; 8366369Sjkh } 8455393Sjkh 8566369Sjkh msgNotify("Checking access to\n %s", variable_get(VAR_HTTP_PATH)); 86248313Sdteske if (isProxy) 87248313Sdteske sprintf(req,"GET %s/ HTTP/1.0\r\n\r\n", variable_get(VAR_HTTP_PATH)); 88248313Sdteske else 89248313Sdteske sprintf(req,"GET /%s/ HTTP/1.0\r\n\r\n", variable_get(VAR_HTTP_PATH)); 9055393Sjkh write(s,req,strlen(req)); 9155393Sjkh/* 9255393Sjkh * scan the headers of the response 9355393Sjkh * this is extremely quick'n dirty 9455393Sjkh * 9555393Sjkh */ 9669647Sjkh bzero(buf, PATH_MAX); 9755393Sjkh cp=buf; 9855393Sjkh el=FALSE; 9955393Sjkh rv=read(s,cp,1); 10055393Sjkh variable_set2(VAR_HTTP_FTP_MODE,"",0); 10155393Sjkh while (rv>0) { 10256573Sjkh if ((*cp == '\012') && el) { 10356573Sjkh /* reached end of a header line */ 10466369Sjkh if (!strncmp(buf,"HTTP",4)) { 10566369Sjkh if (strtol((char *)(buf+9),0,0) == 200) { 10666369Sjkh found = TRUE; 10766369Sjkh } 10866369Sjkh } 10966369Sjkh 110248313Sdteske /* 111248313Sdteske * Some proxies fetch files with certain extensions in "ascii mode" 112248313Sdteske * instead of "binary mode" for FTP. The FTP server then translates 113248313Sdteske * all LF to CRLF. 114248313Sdteske * 115248313Sdteske * You can force Squid to use binary mode by appending ";type=i" to 116248313Sdteske * the URL, which is what I do here. For other proxies, the 117248313Sdteske * LF->CRLF substitution is reverted in distExtract(). 118248313Sdteske */ 119248313Sdteske if (isProxy && !strncmp(buf,"Server: ",8)) { 12056573Sjkh if (!strncmp(buf,"Server: Squid",13)) { 12156573Sjkh variable_set2(VAR_HTTP_FTP_MODE,";type=i",0); 12256573Sjkh } else { 12356573Sjkh variable_set2(VAR_HTTP_FTP_MODE,"",0); 12456573Sjkh } 12556573Sjkh } 12656573Sjkh /* ignore other headers */ 12756573Sjkh /* check for "\015\012" at beginning of line, i.e. end of headers */ 12856573Sjkh if ((cp-buf) == 1) 12956573Sjkh break; 13056573Sjkh cp=buf; 13156573Sjkh rv=read(s,cp,1); 13256573Sjkh } else { 13356573Sjkh el=FALSE; 13456573Sjkh if (*cp == '\015') 13556573Sjkh el=TRUE; 13656573Sjkh cp++; 13756573Sjkh rv=read(s,cp,1); 13856573Sjkh } 13955393Sjkh } 14055393Sjkh close(s); 14169647Sjkh return found; 14269647Sjkh} 14369647Sjkh 14469647SjkhBoolean 14569647SjkhmediaInitHTTP(Device *dev) 14669647Sjkh{ 14769647Sjkh bool found=FALSE; /* end of header line */ 14869647Sjkh char *rel, req[BUFSIZ]; 14969647Sjkh int fdir; 15069647Sjkh 15169647Sjkh /* 15269647Sjkh * First verify the proxy access 15369647Sjkh */ 154248313Sdteske checkAccess(TRUE, TRUE); 15569647Sjkh while (variable_get(VAR_HTTP_HOST) == NULL) { 15669647Sjkh if (DITEM_STATUS(mediaSetHTTP(NULL)) == DITEM_FAILURE) 15769647Sjkh return FALSE; 158248313Sdteske checkAccess(TRUE, TRUE); 15969647Sjkh } 16069647Sjkhagain: 16169647Sjkh /* If the release is specified as "__RELEASE" or "any", then just 16269647Sjkh * assume that the path the user gave is ok. 16369647Sjkh */ 16469647Sjkh rel = variable_get(VAR_RELNAME); 16569647Sjkh /* 16669647Sjkh msgConfirm("rel: -%s-", rel); 16769647Sjkh */ 16869647Sjkh 16969647Sjkh if (strcmp(rel, "__RELEASE") && strcmp(rel, "any")) { 17069647Sjkh for (fdir = 0; ftp_dirs[fdir]; fdir++) { 17169647Sjkh sprintf(req, "%s/%s/%s", variable_get(VAR_FTP_PATH), 17269647Sjkh ftp_dirs[fdir], rel); 17369647Sjkh variable_set2(VAR_HTTP_PATH, req, 0); 174248313Sdteske if (checkAccess(FALSE, TRUE)) { 17569647Sjkh found = TRUE; 17669647Sjkh break; 17769647Sjkh } 17869647Sjkh } 17969647Sjkh } else { 18069647Sjkh variable_set2(VAR_HTTP_PATH, variable_get(VAR_FTP_PATH), 0); 181248313Sdteske found = checkAccess(FALSE, TRUE); 18269647Sjkh } 18369647Sjkh if (!found) { 18466369Sjkh msgConfirm("No such directory: %s\n" 18566369Sjkh "please check the URL and try again.", variable_get(VAR_HTTP_PATH)); 18669647Sjkh variable_unset(VAR_HTTP_PATH); 18769647Sjkh dialog_clear_norefresh(); 18869647Sjkh clear(); 18969647Sjkh if (DITEM_STATUS(mediaSetHTTP(NULL)) != DITEM_FAILURE) goto again; 19069647Sjkh } 19166369Sjkh return found; 19269647Sjkh} 19355393Sjkh 19455393SjkhFILE * 19555393SjkhmediaGetHTTP(Device *dev, char *file, Boolean probe) 19655393Sjkh{ 19755393Sjkh FILE *fp; 19863118Sume int rv, s, af; 19955393Sjkh bool el; /* end of header line */ 20056573Sjkh char *cp, buf[PATH_MAX], req[BUFSIZ]; 20163118Sume struct addrinfo hints, *res, *res0; 20255393Sjkh 20363118Sume af = variable_cmp(VAR_IPV6_ENABLE, "YES") ? AF_INET : AF_UNSPEC; 20463118Sume memset(&hints, 0, sizeof(hints)); 20563118Sume hints.ai_family = af; 20663118Sume hints.ai_socktype = SOCK_STREAM; 20763118Sume hints.ai_protocol = 0; 20863118Sume if ((rv = getaddrinfo(variable_get(VAR_HTTP_HOST), 20963118Sume variable_get(VAR_HTTP_PORT), &hints, &res0)) != 0) { 21063118Sume msgConfirm("%s", gai_strerror(rv)); 21156573Sjkh return NULL; 21255393Sjkh } 21363118Sume s = -1; 21463118Sume for (res = res0; res; res = res->ai_next) { 21563118Sume if ((s = socket(res->ai_family, res->ai_socktype, 21663118Sume res->ai_protocol)) < 0) 21763118Sume continue; 21863118Sume if (connect(s, res->ai_addr, res->ai_addrlen) >= 0) 21963118Sume break; 22063118Sume close(s); 22163118Sume s = -1; 22263118Sume } 22363118Sume freeaddrinfo(res0); 22463118Sume if (s == -1) { 22556573Sjkh msgConfirm("Couldn't connect to proxy %s:%s", 22663118Sume variable_get(VAR_HTTP_HOST),variable_get(VAR_HTTP_PORT)); 22756573Sjkh return NULL; 22855393Sjkh } 22956573Sjkh 23066369Sjkh sprintf(req,"GET %s/%s%s HTTP/1.0\r\n\r\n", 23166369Sjkh variable_get(VAR_HTTP_PATH), file, variable_get(VAR_HTTP_FTP_MODE)); 23256573Sjkh 23356573Sjkh if (isDebug()) { 234106279Skuriyama msgDebug("sending http request: %s\n",req); 23556573Sjkh } 23655393Sjkh write(s,req,strlen(req)); 23755393Sjkh 23855393Sjkh/* 23955393Sjkh * scan the headers of the response 24055393Sjkh * this is extremely quick'n dirty 24155393Sjkh * 24255393Sjkh */ 24355393Sjkh cp=buf; 24455393Sjkh el=FALSE; 24555393Sjkh rv=read(s,cp,1); 24655393Sjkh while (rv>0) { 24756573Sjkh if ((*cp == '\012') && el) { 24856573Sjkh /* reached end of a header line */ 24956573Sjkh if (!strncmp(buf,"HTTP",4)) { 25056573Sjkh rv=strtol((char *)(buf+9),0,0); 25156573Sjkh *(cp-1)='\0'; /* chop the CRLF off */ 25256573Sjkh if (probe && (rv != 200)) { 25356573Sjkh return NULL; 25456573Sjkh } else if (rv >= 500) { 25556573Sjkh msgConfirm("Server error %s when sending %s, you could try an other server",buf, req); 25656573Sjkh return NULL; 25756573Sjkh } else if (rv == 404) { 25856573Sjkh msgConfirm("%s was not found, maybe directory or release-version are wrong?",req); 25956573Sjkh return NULL; 26056573Sjkh } else if (rv >= 400) { 26156573Sjkh msgConfirm("Client error %s, you could try an other server",buf); 26256573Sjkh return NULL; 26356573Sjkh } else if (rv >= 300) { 264244676Sdteske msgConfirm("Error %s",buf); 26556573Sjkh return NULL; 26656573Sjkh } else if (rv != 200) { 26756573Sjkh msgConfirm("Error %s when sending %s, you could try an other server",buf, req); 26856573Sjkh return NULL; 26956573Sjkh } 27056573Sjkh } 27156573Sjkh /* ignore other headers */ 27256573Sjkh /* check for "\015\012" at beginning of line, i.e. end of headers */ 27356573Sjkh if ((cp-buf) == 1) 27456573Sjkh break; 27556573Sjkh cp=buf; 27656573Sjkh rv=read(s,cp,1); 27756573Sjkh } else { 27856573Sjkh el=FALSE; 27956573Sjkh if (*cp == '\015') 28056573Sjkh el=TRUE; 28156573Sjkh cp++; 28256573Sjkh rv=read(s,cp,1); 28356573Sjkh } 28455393Sjkh } 28555393Sjkh fp=fdopen(s,"r"); 28655393Sjkh return fp; 28755393Sjkh} 288