/[axel]/trunk/http.c
ViewVC logotype

Contents of /trunk/http.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6 - (hide annotations) (download)
Tue Jan 15 16:11:35 2008 UTC (5 years, 4 months ago) by appaji-guest
File MIME type: text/plain
File size: 5721 byte(s)
fix segfaults on HTTP404 and HTTP401 responses
1 appaji-guest 2 /********************************************************************\
2     * Axel -- A lighter download accelerator for Linux and other Unices. *
3     * *
4     * Copyright 2001 Wilmer van der Gaast *
5     \********************************************************************/
6    
7     /* HTTP control file */
8    
9     /*
10     This program is free software; you can redistribute it and/or modify
11     it under the terms of the GNU General Public License as published by
12     the Free Software Foundation; either version 2 of the License, or
13     (at your option) any later version.
14    
15     This program is distributed in the hope that it will be useful,
16     but WITHOUT ANY WARRANTY; without even the implied warranty of
17     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18     GNU General Public License for more details.
19    
20     You should have received a copy of the GNU General Public License with
21     the Debian GNU/Linux distribution in file /usr/doc/copyright/GPL;
22     if not, write to the Free Software Foundation, Inc., 59 Temple Place,
23     Suite 330, Boston, MA 02111-1307 USA
24     */
25    
26     #include "axel.h"
27    
28     int http_connect( http_t *conn, int proto, char *proxy, char *host, int port, char *user, char *pass )
29     {
30     char base64_encode[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
31     "abcdefghijklmnopqrstuvwxyz0123456789+/";
32     char auth[MAX_STRING];
33     conn_t tconn[1];
34     int i;
35    
36     strncpy( conn->host, host, MAX_STRING );
37     conn->proto = proto;
38    
39     if( proxy != NULL ) { if( *proxy != 0 )
40     {
41     sprintf( conn->host, "%s:%i", host, port );
42     if( !conn_set( tconn, proxy ) )
43     {
44 appaji-guest 6 /* We'll put the message in conn->headers, not in request */
45     sprintf( conn->headers, _("Invalid proxy string: %s\n"), proxy );
46 appaji-guest 2 return( 0 );
47     }
48     host = tconn->host;
49     port = tconn->port;
50     conn->proxy = 1;
51     }
52     else
53     {
54     conn->proxy = 0;
55     } }
56    
57     if( ( conn->fd = tcp_connect( host, port, conn->local_if ) ) == -1 )
58     {
59 appaji-guest 6 /* We'll put the message in conn->headers, not in request */
60     sprintf( conn->headers, _("Unable to connect to server %s:%i\n"), host, port );
61 appaji-guest 2 return( 0 );
62     }
63    
64     if( *user == 0 )
65     {
66     *conn->auth = 0;
67     }
68     else
69     {
70     memset( auth, 0, MAX_STRING );
71     snprintf( auth, MAX_STRING, "%s:%s", user, pass );
72     for( i = 0; auth[i*3]; i ++ )
73     {
74     conn->auth[i*4] = base64_encode[(auth[i*3]>>2)];
75     conn->auth[i*4+1] = base64_encode[((auth[i*3]&3)<<4)|(auth[i*3+1]>>4)];
76     conn->auth[i*4+2] = base64_encode[((auth[i*3+1]&15)<<2)|(auth[i*3+2]>>6)];
77     conn->auth[i*4+3] = base64_encode[auth[i*3+2]&63];
78     if( auth[i*3+2] == 0 ) conn->auth[i*4+3] = '=';
79     if( auth[i*3+1] == 0 ) conn->auth[i*4+2] = '=';
80     }
81     }
82    
83     return( 1 );
84     }
85    
86     void http_disconnect( http_t *conn )
87     {
88     if( conn->fd > 0 )
89     close( conn->fd );
90     conn->fd = -1;
91     }
92    
93     void http_get( http_t *conn, char *lurl )
94     {
95     *conn->request = 0;
96     if( conn->proxy )
97     {
98     http_addheader( conn, "GET %s://%s%s HTTP/1.0",
99     conn->proto == PROTO_HTTP ? "http" : "ftp", conn->host, lurl );
100     }
101     else
102     {
103     http_addheader( conn, "GET %s HTTP/1.0", lurl );
104     http_addheader( conn, "Host: %s", conn->host );
105     }
106     http_addheader( conn, "User-Agent: %s", USER_AGENT );
107     if( *conn->auth )
108     http_addheader( conn, "Authorization: Basic %s", conn->auth );
109     if( conn->firstbyte )
110     {
111     if( conn->lastbyte )
112     http_addheader( conn, "Range: bytes=%i-%i", conn->firstbyte, conn->lastbyte );
113     else
114     http_addheader( conn, "Range: bytes=%i-", conn->firstbyte );
115     }
116     }
117    
118     void http_addheader( http_t *conn, char *format, ... )
119     {
120     char s[MAX_STRING];
121     va_list params;
122    
123     va_start( params, format );
124     vsnprintf( s, MAX_STRING - 3, format, params );
125     strcat( s, "\r\n" );
126     va_end( params );
127    
128     strncat( conn->request, s, MAX_QUERY );
129     }
130    
131     int http_exec( http_t *conn )
132     {
133     int i = 0;
134     char s[2] = " ", *s2;
135    
136     #ifdef DEBUG
137     fprintf( stderr, "--- Sending request ---\n%s--- End of request ---\n", conn->request );
138     #endif
139    
140     http_addheader( conn, "" );
141     write( conn->fd, conn->request, strlen( conn->request ) );
142    
143     *conn->headers = 0;
144     /* Read the headers byte by byte to make sure we don't touch the
145     actual data */
146     while( 1 )
147     {
148     if( read( conn->fd, s, 1 ) <= 0 )
149     {
150 appaji-guest 6 /* We'll put the message in conn->headers, not in request */
151     sprintf( conn->headers, _("Connection gone.\n") );
152 appaji-guest 2 return( 0 );
153     }
154     if( *s == '\r' )
155     {
156     continue;
157     }
158     else if( *s == '\n' )
159     {
160     if( i == 0 )
161     break;
162     i = 0;
163     }
164     else
165     {
166     i ++;
167     }
168     strncat( conn->headers, s, MAX_QUERY );
169     }
170    
171     #ifdef DEBUG
172     fprintf( stderr, "--- Reply headers ---\n%s--- End of headers ---\n", conn->headers );
173     #endif
174    
175     sscanf( conn->headers, "%*s %3i", &conn->status );
176     s2 = strchr( conn->headers, '\n' ); *s2 = 0;
177     strcpy( conn->request, conn->headers );
178     *s2 = '\n';
179    
180     return( 1 );
181     }
182    
183     char *http_header( http_t *conn, char *header )
184     {
185     char s[32];
186     int i;
187    
188     for( i = 1; conn->headers[i]; i ++ )
189     if( conn->headers[i-1] == '\n' )
190     {
191     sscanf( &conn->headers[i], "%31s", s );
192     if( strcasecmp( s, header ) == 0 )
193     return( &conn->headers[i+strlen(header)] );
194     }
195    
196     return( NULL );
197     }
198    
199     int http_size( http_t *conn )
200     {
201     char *i;
202     int j;
203    
204     if( ( i = http_header( conn, "Content-Length:" ) ) == NULL )
205     return( -2 );
206    
207     sscanf( i, "%i", &j );
208     return( j );
209     }
210    
211     /* Decode%20a%20file%20name */
212     void http_decode( char *s )
213     {
214     char t[MAX_STRING];
215     int i, j, k;
216    
217     for( i = j = 0; s[i]; i ++, j ++ )
218     {
219     t[j] = s[i];
220     if( s[i] == '%' )
221     if( sscanf( s + i + 1, "%2x", &k ) )
222     {
223     t[j] = k;
224     i += 2;
225     }
226     }
227     t[j] = 0;
228    
229     strcpy( s, t );
230     }
231    
232     void http_encode( char *s )
233     {
234     char t[MAX_STRING];
235     int i, j;
236    
237     for( i = j = 0; s[i]; i ++, j ++ )
238     {
239     t[j] = s[i];
240     if( s[i] == ' ' )
241     {
242     strcpy( t + j, "%20" );
243     j += 2;
244     }
245     }
246     t[j] = 0;
247    
248     strcpy( s, t );
249     }

  ViewVC Help
Powered by ViewVC 1.1.5