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

Contents of /trunk/conn.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 14 - (show annotations) (download)
Wed Jan 16 07:56:47 2008 UTC (5 years, 4 months ago) by appaji-guest
File MIME type: text/plain
File size: 8483 byte(s)
Use strncpy instead of strcpy for length sensitive copies
1 /********************************************************************\
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 strncpy( conn->file, conn->dir, MAX_STRING );
78 strcpy( conn->dir, "/" );
79 }
80 else
81 {
82 strncpy( conn->file, i + 1, MAX_STRING );
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 strncpy( conn->host, i + 1, MAX_STRING );
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 strncpy( conn->pass, i + 1, MAX_STRING );
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 if( !conn_setup( conn ) )
317 return( 0 );
318 conn_exec( conn );
319 conn_disconnect( conn );
320 /* Code 3xx == redirect */
321 if( conn->http->status / 100 != 3 )
322 break;
323 if( ( t = http_header( conn->http, "location:" ) ) == NULL )
324 return( 0 );
325 sscanf( t, "%255s", s );
326 if( strstr( s, "://" ) == NULL)
327 {
328 sprintf( conn->http->headers, "%s%s",
329 conn_url( conn ), s );
330 strncpy( s, conn->http->headers, MAX_STRING );
331 }
332 else if( s[0] == '/' )
333 {
334 sprintf( conn->http->headers, "http://%s:%i%s",
335 conn->host, conn->port, s );
336 strncpy( s, conn->http->headers, MAX_STRING );
337 }
338 conn_set( conn, s );
339 i ++;
340 }
341 while( conn->http->status / 100 == 3 && i < MAX_REDIR );
342
343 if( i == MAX_REDIR )
344 {
345 sprintf( conn->message, _("Too many redirects.\n") );
346 return( 0 );
347 }
348
349 conn->size = http_size( conn->http );
350 if( conn->http->status == 206 && conn->size >= 0 )
351 {
352 conn->supported = 1;
353 conn->size ++;
354 }
355 else if( conn->http->status == 200 || conn->http->status == 206 )
356 {
357 conn->supported = 0;
358 conn->size = INT_MAX;
359 }
360 else
361 {
362 t = strchr( conn->message, '\n' );
363 if( t == NULL )
364 sprintf( conn->message, _("Unknown HTTP error.\n") );
365 else
366 *t = 0;
367 return( 0 );
368 }
369 }
370
371 return( 1 );
372 }

  ViewVC Help
Powered by ViewVC 1.1.5