/[axel]/tags/1.0b/conn.c
ViewVC logotype

Contents of /tags/1.0b/conn.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4 - (hide annotations) (download)
Fri Jan 11 12:03:59 2008 UTC (5 years, 4 months ago) by appaji-guest
Original Path: trunk/conn.c
File MIME type: text/plain
File size: 8408 byte(s)
Import 1.0b
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     strcpy( conn->file, conn->dir );
78     strcpy( conn->dir, "/" );
79     }
80     else
81     {
82     strcpy( conn->file, i + 1 );
83     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     strcpy( conn->host, i + 1 );
93     *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     strcpy( conn->pass, i + 1 );
116     }
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     ftp_command( conn->ftp, "REST %i", conn->currentbyte );
246     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    
255     snprintf( s, MAX_STRING, "%s%s", conn->dir, conn->file );
256     conn->http->firstbyte = conn->currentbyte;
257     conn->http->lastbyte = conn->lastbyte;
258     http_get( conn->http, s );
259     }
260     return( 1 );
261     }
262    
263     int conn_exec( conn_t *conn )
264     {
265     if( conn->proto == PROTO_FTP && !conn->proxy )
266     {
267     if( !ftp_command( conn->ftp, "RETR %s", conn->file ) )
268     return( 0 );
269     return( ftp_wait( conn->ftp ) / 100 == 1 );
270     }
271     else
272     {
273     if( !http_exec( conn->http ) )
274     return( 0 );
275     return( conn->http->status / 100 == 2 );
276     }
277     }
278    
279     /* Get file size and other information */
280     int conn_info( conn_t *conn )
281     {
282     /* It's all a bit messed up.. But it works. */
283     if( conn->proto == PROTO_FTP && !conn->proxy )
284     {
285     ftp_command( conn->ftp, "REST %i", 1 );
286     if( ftp_wait( conn->ftp ) / 100 == 3 ||
287     conn->ftp->status / 100 == 2 )
288     {
289     conn->supported = 1;
290     ftp_command( conn->ftp, "REST %i", 0 );
291     ftp_wait( conn->ftp );
292     }
293     else
294     {
295     conn->supported = 0;
296     }
297    
298     if( !ftp_cwd( conn->ftp, conn->dir ) )
299     return( 0 );
300     conn->size = ftp_size( conn->ftp, conn->file, MAX_REDIR );
301     if( conn->size < 0 )
302     conn->supported = 0;
303     if( conn->size == -1 )
304     return( 0 );
305     else if( conn->size == -2 )
306     conn->size = INT_MAX;
307     }
308     else
309     {
310     char s[MAX_STRING], *t;
311     int i = 0;
312    
313     do
314     {
315     conn->currentbyte = 1;
316     conn_setup( conn );
317     conn_exec( conn );
318     conn_disconnect( conn );
319     /* Code 3xx == redirect */
320     if( conn->http->status / 100 != 3 )
321     break;
322     if( ( t = http_header( conn->http, "location:" ) ) == NULL )
323     return( 0 );
324 appaji-guest 4 sscanf( t, "%255s", s );
325 appaji-guest 2 if( strstr( s, "://" ) == NULL)
326     {
327     sprintf( conn->http->headers, "%s%s",
328     conn_url( conn ), s );
329     strncpy( s, conn->http->headers, MAX_STRING );
330     }
331     else if( s[0] == '/' )
332     {
333     sprintf( conn->http->headers, "http://%s:%i%s",
334     conn->host, conn->port, s );
335     strncpy( s, conn->http->headers, MAX_STRING );
336     }
337     conn_set( conn, s );
338     i ++;
339     }
340     while( conn->http->status / 100 == 3 && i < MAX_REDIR );
341    
342     if( i == MAX_REDIR )
343     {
344     sprintf( conn->message, _("Too many redirects.\n") );
345     return( 0 );
346     }
347    
348     conn->size = http_size( conn->http );
349     if( conn->http->status == 206 && conn->size >= 0 )
350     {
351     conn->supported = 1;
352     conn->size ++;
353     }
354     else if( conn->http->status == 200 || conn->http->status == 206 )
355     {
356     conn->supported = 0;
357     conn->size = INT_MAX;
358     }
359     else
360     {
361     t = strchr( conn->message, '\n' );
362     if( t == NULL )
363     sprintf( conn->message, _("Unknown HTTP error.\n") );
364     else
365     *t = 0;
366     return( 0 );
367     }
368     }
369    
370     return( 1 );
371     }

  ViewVC Help
Powered by ViewVC 1.1.5