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

Contents of /trunk/conn.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 27 - (hide annotations) (download)
Thu Apr 3 11:01:31 2008 UTC (5 years, 1 month ago) by appaji-guest
File MIME type: text/plain
File size: 8625 byte(s)
Custom header support, thanks Eli Yukelzon
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     /* Connection stuff */
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     char string[MAX_STRING];
29    
30     /* Convert an URL to a conn_t structure */
31     int conn_set( conn_t *conn, char *set_url )
32     {
33     char url[MAX_STRING];
34     char *i, *j;
35    
36     /* protocol:// */
37     if( ( i = strstr( set_url, "://" ) ) == NULL )
38     {
39     conn->proto = PROTO_DEFAULT;
40     strncpy( url, set_url, MAX_STRING );
41     }
42     else
43     {
44     if( set_url[0] == 'f' )
45     conn->proto = PROTO_FTP;
46     else if( set_url[0] == 'h' )
47     conn->proto = PROTO_HTTP;
48     else
49     {
50     return( 0 );
51     }
52     strncpy( url, i + 3, MAX_STRING );
53     }
54    
55     /* Split */
56     if( ( i = strchr( url, '/' ) ) == NULL )
57     {
58     strcpy( conn->dir, "/" );
59     }
60     else
61     {
62     *i = 0;
63     snprintf( conn->dir, MAX_STRING, "/%s", i + 1 );
64     if( conn->proto == PROTO_HTTP )
65     http_encode( conn->dir );
66     }
67     strncpy( conn->host, url, MAX_STRING );
68     j = strchr( conn->dir, '?' );
69     if( j != NULL )
70     *j = 0;
71     i = strrchr( conn->dir, '/' );
72     *i = 0;
73     if( j != NULL )
74     *j = '?';
75     if( i == NULL )
76     {
77 appaji-guest 14 strncpy( conn->file, conn->dir, MAX_STRING );
78 appaji-guest 2 strcpy( conn->dir, "/" );
79     }
80     else
81     {
82 appaji-guest 14 strncpy( conn->file, i + 1, MAX_STRING );
83 appaji-guest 2 strcat( conn->dir, "/" );
84     }
85    
86     /* Check for username in host field */
87     if( strrchr( conn->host, '@' ) != NULL )
88     {
89     strncpy( conn->user, conn->host, MAX_STRING );
90     i = strrchr( conn->user, '@' );
91     *i = 0;
92 appaji-guest 14 strncpy( conn->host, i + 1, MAX_STRING );
93 appaji-guest 2 *conn->pass = 0;
94     }
95     /* If not: Fill in defaults */
96     else
97     {
98     if( conn->proto == PROTO_FTP )
99     {
100     /* Dash the password: Save traffic by trying
101     to avoid multi-line responses */
102     strcpy( conn->user, "anonymous" );
103     strcpy( conn->pass, "-lara_hack@gmx.co.uk" );
104     }
105     else
106     {
107     *conn->user = *conn->pass = 0;
108     }
109     }
110    
111     /* Password? */
112     if( ( i = strchr( conn->user, ':' ) ) != NULL )
113     {
114     *i = 0;
115 appaji-guest 14 strncpy( conn->pass, i + 1, MAX_STRING );
116 appaji-guest 2 }
117     /* Port number? */
118     if( ( i = strchr( conn->host, ':' ) ) != NULL )
119     {
120     *i = 0;
121     sscanf( i + 1, "%i", &conn->port );
122     }
123     /* Take default port numbers from /etc/services */
124     else
125     {
126     #ifndef DARWIN
127     struct servent *serv;
128    
129     if( conn->proto == PROTO_FTP )
130     serv = getservbyname( "ftp", "tcp" );
131     else
132     serv = getservbyname( "www", "tcp" );
133    
134     if( serv )
135     conn->port = ntohs( serv->s_port );
136     else
137     #endif
138     if( conn->proto == PROTO_HTTP )
139     conn->port = 80;
140     else
141     conn->port = 21;
142     }
143    
144     return( conn->port > 0 );
145     }
146    
147     /* Generate a nice URL string. */
148     char *conn_url( conn_t *conn )
149     {
150     if( conn->proto == PROTO_FTP )
151     strcpy( string, "ftp://" );
152     else
153     strcpy( string, "http://" );
154    
155     if( *conn->user != 0 && strcmp( conn->user, "anonymous" ) != 0 )
156     sprintf( string + strlen( string ), "%s:%s@",
157     conn->user, conn->pass );
158    
159     sprintf( string + strlen( string ), "%s:%i%s%s",
160     conn->host, conn->port, conn->dir, conn->file );
161    
162     return( string );
163     }
164    
165     /* Simple... */
166     void conn_disconnect( conn_t *conn )
167     {
168     if( conn->proto == PROTO_FTP && !conn->proxy )
169     ftp_disconnect( conn->ftp );
170     else
171     http_disconnect( conn->http );
172     conn->fd = -1;
173     }
174    
175     int conn_init( conn_t *conn )
176     {
177     char *proxy = conn->conf->http_proxy, *host = conn->conf->no_proxy;
178     int i;
179    
180     if( *conn->conf->http_proxy == 0 )
181     {
182     proxy = NULL;
183     }
184     else if( *conn->conf->no_proxy != 0 )
185     {
186     for( i = 0; ; i ++ )
187     if( conn->conf->no_proxy[i] == 0 )
188     {
189     if( strstr( conn->host, host ) != NULL )
190     proxy = NULL;
191     host = &conn->conf->no_proxy[i+1];
192     if( conn->conf->no_proxy[i+1] == 0 )
193     break;
194     }
195     }
196    
197     conn->proxy = proxy != NULL;
198    
199     if( conn->proto == PROTO_FTP && !conn->proxy )
200     {
201     conn->ftp->local_if = conn->local_if;
202     conn->ftp->ftp_mode = FTP_PASSIVE;
203     if( !ftp_connect( conn->ftp, conn->host, conn->port, conn->user, conn->pass ) )
204     {
205     conn->message = conn->ftp->message;
206     conn_disconnect( conn );
207     return( 0 );
208     }
209     conn->message = conn->ftp->message;
210     if( !ftp_cwd( conn->ftp, conn->dir ) )
211     {
212     conn_disconnect( conn );
213     return( 0 );
214     }
215     }
216     else
217     {
218     conn->http->local_if = conn->local_if;
219     if( !http_connect( conn->http, conn->proto, proxy, conn->host, conn->port, conn->user, conn->pass ) )
220     {
221     conn->message = conn->http->headers;
222     conn_disconnect( conn );
223     return( 0 );
224     }
225     conn->message = conn->http->headers;
226     conn->fd = conn->http->fd;
227     }
228     return( 1 );
229     }
230    
231     int conn_setup( conn_t *conn )
232     {
233     if( conn->ftp->fd <= 0 && conn->http->fd <= 0 )
234     if( !conn_init( conn ) )
235     return( 0 );
236    
237     if( conn->proto == PROTO_FTP && !conn->proxy )
238     {
239     if( !ftp_data( conn->ftp ) ) /* Set up data connnection */
240     return( 0 );
241     conn->fd = conn->ftp->data_fd;
242    
243     if( conn->currentbyte )
244     {
245 appaji-guest 25 ftp_command( conn->ftp, "REST %lld", conn->currentbyte );
246 appaji-guest 2 if( ftp_wait( conn->ftp ) / 100 != 3 &&
247     conn->ftp->status / 100 != 2 )
248     return( 0 );
249     }
250     }
251     else
252     {
253     char s[MAX_STRING];
254 appaji-guest 27 int i;
255    
256 appaji-guest 2 snprintf( s, MAX_STRING, "%s%s", conn->dir, conn->file );
257     conn->http->firstbyte = conn->currentbyte;
258     conn->http->lastbyte = conn->lastbyte;
259     http_get( conn->http, s );
260 appaji-guest 27 for( i = 0; i < conn->conf->add_header_count; i++)
261     http_addheader( conn->http, "%s", conn->conf->add_header[i] );
262 appaji-guest 2 }
263     return( 1 );
264     }
265    
266     int conn_exec( conn_t *conn )
267     {
268     if( conn->proto == PROTO_FTP && !conn->proxy )
269     {
270     if( !ftp_command( conn->ftp, "RETR %s", conn->file ) )
271     return( 0 );
272     return( ftp_wait( conn->ftp ) / 100 == 1 );
273     }
274     else
275     {
276     if( !http_exec( conn->http ) )
277     return( 0 );
278     return( conn->http->status / 100 == 2 );
279     }
280     }
281    
282     /* Get file size and other information */
283     int conn_info( conn_t *conn )
284     {
285     /* It's all a bit messed up.. But it works. */
286     if( conn->proto == PROTO_FTP && !conn->proxy )
287     {
288 appaji-guest 25 ftp_command( conn->ftp, "REST %lld", 1 );
289 appaji-guest 2 if( ftp_wait( conn->ftp ) / 100 == 3 ||
290     conn->ftp->status / 100 == 2 )
291     {
292     conn->supported = 1;
293 appaji-guest 25 ftp_command( conn->ftp, "REST %lld", 0 );
294 appaji-guest 2 ftp_wait( conn->ftp );
295     }
296     else
297     {
298     conn->supported = 0;
299     }
300    
301     if( !ftp_cwd( conn->ftp, conn->dir ) )
302     return( 0 );
303     conn->size = ftp_size( conn->ftp, conn->file, MAX_REDIR );
304     if( conn->size < 0 )
305     conn->supported = 0;
306     if( conn->size == -1 )
307     return( 0 );
308     else if( conn->size == -2 )
309     conn->size = INT_MAX;
310     }
311     else
312     {
313     char s[MAX_STRING], *t;
314 appaji-guest 25 long long int i = 0;
315 appaji-guest 2
316     do
317     {
318     conn->currentbyte = 1;
319 appaji-guest 8 if( !conn_setup( conn ) )
320     return( 0 );
321 appaji-guest 2 conn_exec( conn );
322     conn_disconnect( conn );
323     /* Code 3xx == redirect */
324     if( conn->http->status / 100 != 3 )
325     break;
326     if( ( t = http_header( conn->http, "location:" ) ) == NULL )
327     return( 0 );
328 appaji-guest 4 sscanf( t, "%255s", s );
329 appaji-guest 2 if( strstr( s, "://" ) == NULL)
330     {
331     sprintf( conn->http->headers, "%s%s",
332     conn_url( conn ), s );
333     strncpy( s, conn->http->headers, MAX_STRING );
334     }
335     else if( s[0] == '/' )
336     {
337     sprintf( conn->http->headers, "http://%s:%i%s",
338     conn->host, conn->port, s );
339     strncpy( s, conn->http->headers, MAX_STRING );
340     }
341     conn_set( conn, s );
342     i ++;
343     }
344     while( conn->http->status / 100 == 3 && i < MAX_REDIR );
345    
346     if( i == MAX_REDIR )
347     {
348     sprintf( conn->message, _("Too many redirects.\n") );
349     return( 0 );
350     }
351    
352     conn->size = http_size( conn->http );
353     if( conn->http->status == 206 && conn->size >= 0 )
354     {
355     conn->supported = 1;
356     conn->size ++;
357     }
358     else if( conn->http->status == 200 || conn->http->status == 206 )
359     {
360     conn->supported = 0;
361     conn->size = INT_MAX;
362     }
363     else
364     {
365     t = strchr( conn->message, '\n' );
366     if( t == NULL )
367     sprintf( conn->message, _("Unknown HTTP error.\n") );
368     else
369     *t = 0;
370     return( 0 );
371     }
372     }
373    
374     return( 1 );
375     }

  ViewVC Help
Powered by ViewVC 1.1.5