]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/getputfile.c
Fix httpFlush() and friends when doing PUT or OPTION requests (STR #558)
[thirdparty/cups.git] / cups / getputfile.c
1 /*
2 * "$Id: getputfile.c,v 1.3 2004/02/04 19:06:49 mike Exp $"
3 *
4 * Get/put file functions for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2003 by Easy Software Products.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636-3111 USA
19 *
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * This file is subject to the Apple OS-Developed Software exception.
25 *
26 * Contents:
27 *
28 * cupsGetFd() - Get a file from the server.
29 * cupsGetFile() - Get a file from the server.
30 * cupsPutFd() - Put a file on the server.
31 * cupsPutFile() - Put a file on the server.
32 */
33
34 /*
35 * Include necessary headers...
36 */
37
38 #include "cups.h"
39 #include "ipp.h"
40 #include "language.h"
41 #include "string.h"
42 #include "debug.h"
43 #include <stdlib.h>
44 #include <ctype.h>
45 #include <errno.h>
46 #include <fcntl.h>
47 #include <sys/stat.h>
48 #if defined(WIN32) || defined(__EMX__)
49 # include <io.h>
50 #else
51 # include <unistd.h>
52 #endif /* WIN32 || __EMX__ */
53
54
55 /*
56 * 'cupsGetFd()' - Get a file from the server.
57 */
58
59 http_status_t /* O - Status */
60 cupsGetFd(http_t *http, /* I - HTTP connection to server */
61 const char *resource, /* I - Resource name */
62 int fd) /* I - File descriptor */
63 {
64 int bytes; /* Number of bytes read */
65 char buffer[8192]; /* Buffer for file */
66 http_status_t status; /* HTTP status from server */
67
68
69 /*
70 * Range check input...
71 */
72
73 DEBUG_printf(("cupsGetFd(http=%p, resource=\"%s\", fd=%d)\n", http,
74 resource, fd));
75
76 if (!http || !resource || fd < 0)
77 {
78 if (http)
79 http->error = EINVAL;
80
81 return (HTTP_ERROR);
82 }
83
84 /*
85 * Then send GET requests to the HTTP server...
86 */
87
88 do
89 {
90 httpClearFields(http);
91 httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
92
93 if (httpGet(http, resource))
94 {
95 if (httpReconnect(http))
96 {
97 status = HTTP_ERROR;
98 break;
99 }
100 else
101 {
102 status = HTTP_UNAUTHORIZED;
103 continue;
104 }
105 }
106
107 while ((status = httpUpdate(http)) == HTTP_CONTINUE);
108
109 if (status == HTTP_UNAUTHORIZED)
110 {
111 /*
112 * Flush any error message...
113 */
114
115 httpFlush(http);
116
117 /*
118 * See if we can do authentication...
119 */
120
121 if (cupsDoAuthentication(http, "GET", resource))
122 break;
123
124 httpReconnect(http);
125
126 continue;
127 }
128 else if (status == HTTP_ERROR)
129 {
130 #ifdef WIN32
131 if (http->error != WSAENETDOWN && http->error != WSAENETUNREACH)
132 #else
133 if (http->error != ENETDOWN && http->error != ENETUNREACH)
134 #endif /* WIN32 */
135 continue;
136 else
137 break;
138 }
139 #ifdef HAVE_LIBSSL
140 else if (status == HTTP_UPGRADE_REQUIRED)
141 {
142 /* Flush any error message... */
143 httpFlush(http);
144
145 /* Reconnect... */
146 httpReconnect(http);
147
148 /* Upgrade with encryption... */
149 httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
150
151 /* Try again, this time with encryption enabled... */
152 continue;
153 }
154 #endif /* HAVE_LIBSSL */
155 }
156 while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED ||
157 status == HTTP_ERROR);
158
159 /*
160 * See if we actually got the file or an error...
161 */
162
163 if (status == HTTP_OK)
164 {
165 /*
166 * Yes, copy the file...
167 */
168
169 while ((bytes = httpRead(http, buffer, sizeof(buffer))) > 0)
170 write(fd, buffer, bytes);
171 }
172 else
173 httpFlush(http);
174
175 /*
176 * Return the request status...
177 */
178
179 return (status);
180 }
181
182
183 /*
184 * 'cupsGetFile()' - Get a file from the server.
185 */
186
187 http_status_t /* O - Status */
188 cupsGetFile(http_t *http, /* I - HTTP connection to server */
189 const char *resource, /* I - Resource name */
190 const char *filename) /* I - Filename */
191 {
192 int fd; /* File descriptor */
193 http_status_t status; /* Status */
194
195
196 /*
197 * Range check input...
198 */
199
200 if (!http || !resource || !filename)
201 {
202 if (http)
203 http->error = EINVAL;
204
205 return (HTTP_ERROR);
206 }
207
208 /*
209 * Create the file...
210 */
211
212 if ((fd = open(filename, O_WRONLY | O_EXCL | O_TRUNC)) < 0)
213 {
214 /*
215 * Couldn't open the file!
216 */
217
218 http->error = errno;
219
220 return (HTTP_ERROR);
221 }
222
223 /*
224 * Get the file...
225 */
226
227 status = cupsGetFd(http, resource, fd);
228
229 /*
230 * If the file couldn't be gotten, then remove the file...
231 */
232
233 close(fd);
234
235 if (status != HTTP_OK)
236 unlink(filename);
237
238 /*
239 * Return the HTTP status code...
240 */
241
242 return (status);
243 }
244
245
246 /*
247 * 'cupsPutFd()' - Put a file on the server.
248 */
249
250 http_status_t /* O - Status */
251 cupsPutFd(http_t *http, /* I - HTTP connection to server */
252 const char *resource, /* I - Resource name */
253 int fd) /* I - File descriptor */
254 {
255 int bytes; /* Number of bytes read */
256 char buffer[8192]; /* Buffer for file */
257 http_status_t status; /* HTTP status from server */
258
259
260 /*
261 * Range check input...
262 */
263
264 DEBUG_printf(("cupsPutFd(http=%p, resource=\"%s\", fd=%d)\n", http,
265 resource, fd));
266
267 if (!http || !resource || fd < 0)
268 {
269 if (http)
270 http->error = EINVAL;
271
272 return (HTTP_ERROR);
273 }
274
275 /*
276 * Then send PUT requests to the HTTP server...
277 */
278
279 do
280 {
281 httpClearFields(http);
282 httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
283 httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, "chunked");
284
285 if (httpPut(http, resource))
286 {
287 if (httpReconnect(http))
288 {
289 status = HTTP_ERROR;
290 break;
291 }
292 else
293 {
294 status = HTTP_UNAUTHORIZED;
295 continue;
296 }
297 }
298
299 /*
300 * Copy the file...
301 */
302
303 lseek(fd, 0, SEEK_SET);
304
305 status = HTTP_CONTINUE;
306
307 while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
308 if (httpCheck(http))
309 {
310 if ((status = httpUpdate(http)) != HTTP_CONTINUE)
311 break;
312 }
313 else
314 httpWrite(http, buffer, bytes);
315
316 if (status == HTTP_CONTINUE)
317 {
318 httpWrite(http, buffer, 0);
319
320 while ((status = httpUpdate(http)) == HTTP_CONTINUE);
321 }
322
323 if (status == HTTP_UNAUTHORIZED)
324 {
325 /*
326 * Flush any error message...
327 */
328
329 httpFlush(http);
330
331 /*
332 * See if we can do authentication...
333 */
334
335 if (cupsDoAuthentication(http, "PUT", resource))
336 break;
337
338 httpReconnect(http);
339
340 continue;
341 }
342 else if (status == HTTP_ERROR)
343 {
344 #ifdef WIN32
345 if (http->error != WSAENETDOWN && http->error != WSAENETUNREACH)
346 #else
347 if (http->error != ENETDOWN && http->error != ENETUNREACH)
348 #endif /* WIN32 */
349 continue;
350 else
351 break;
352 }
353 #ifdef HAVE_LIBSSL
354 else if (status == HTTP_UPGRADE_REQUIRED)
355 {
356 /* Flush any error message... */
357 httpFlush(http);
358
359 /* Reconnect... */
360 httpReconnect(http);
361
362 /* Upgrade with encryption... */
363 httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
364
365 /* Try again, this time with encryption enabled... */
366 continue;
367 }
368 #endif /* HAVE_LIBSSL */
369 }
370 while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED ||
371 status == HTTP_ERROR);
372
373 /*
374 * See if we actually put the file or an error...
375 */
376
377 if (status != HTTP_CREATED)
378 httpFlush(http);
379
380 return (status);
381 }
382
383
384 /*
385 * 'cupsPutFile()' - Put a file on the server.
386 */
387
388 http_status_t /* O - Status */
389 cupsPutFile(http_t *http, /* I - HTTP connection to server */
390 const char *resource, /* I - Resource name */
391 const char *filename) /* I - Filename */
392 {
393 int fd; /* File descriptor */
394 http_status_t status; /* Status */
395
396
397 /*
398 * Range check input...
399 */
400
401 if (!http || !resource || !filename)
402 {
403 if (http)
404 http->error = EINVAL;
405
406 return (HTTP_ERROR);
407 }
408
409 /*
410 * Open the local file...
411 */
412
413 if ((fd = open(filename, O_RDONLY)) < 0)
414 {
415 /*
416 * Couldn't open the file!
417 */
418
419 http->error = errno;
420
421 return (HTTP_ERROR);
422 }
423
424 /*
425 * Put the file...
426 */
427
428 status = cupsPutFd(http, resource, fd);
429
430 close(fd);
431
432 return (status);
433 }
434
435
436 /*
437 * End of "$Id: getputfile.c,v 1.3 2004/02/04 19:06:49 mike Exp $".
438 */