]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/getputfile.c
Merge changes from CUPS 1.4svn-r8606.
[thirdparty/cups.git] / cups / getputfile.c
CommitLineData
ef416fc2 1/*
75bd9771 2 * "$Id: getputfile.c 7359 2008-02-29 19:01:35Z mike $"
ef416fc2 3 *
4 * Get/put file functions for the Common UNIX Printing System (CUPS).
5 *
e07d4801 6 * Copyright 2007-2009 by Apple Inc.
ef416fc2 7 * Copyright 1997-2006 by Easy Software Products.
8 *
9 * These coded instructions, statements, and computer programs are the
bc44d920 10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
ef416fc2 14 *
15 * This file is subject to the Apple OS-Developed Software exception.
16 *
17 * Contents:
18 *
19 * cupsGetFd() - Get a file from the server.
20 * cupsGetFile() - Get a file from the server.
21 * cupsPutFd() - Put a file on the server.
22 * cupsPutFile() - Put a file on the server.
23 */
24
25/*
26 * Include necessary headers...
27 */
28
355e94dc 29#include "globals.h"
ef416fc2 30#include "cups.h"
ef416fc2 31#include "language.h"
ef416fc2 32#include "debug.h"
33#include <stdlib.h>
34#include <ctype.h>
35#include <errno.h>
36#include <fcntl.h>
37#include <sys/stat.h>
38#if defined(WIN32) || defined(__EMX__)
39# include <io.h>
40#else
41# include <unistd.h>
42#endif /* WIN32 || __EMX__ */
43
44
45/*
46 * 'cupsGetFd()' - Get a file from the server.
47 *
5a738aea 48 * This function returns @code HTTP_OK@ when the file is successfully retrieved.
ef416fc2 49 *
426c6a59 50 * @since CUPS 1.1.20/Mac OS X 10.4@
ef416fc2 51 */
52
ecdc0628 53http_status_t /* O - HTTP status */
568fa3fa 54cupsGetFd(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
ef416fc2 55 const char *resource, /* I - Resource name */
56 int fd) /* I - File descriptor */
57{
58 int bytes; /* Number of bytes read */
59 char buffer[8192]; /* Buffer for file */
60 http_status_t status; /* HTTP status from server */
757d2cad 61 char if_modified_since[HTTP_MAX_VALUE];
62 /* If-Modified-Since header */
ef416fc2 63
64
65 /*
66 * Range check input...
67 */
68
e07d4801 69 DEBUG_printf(("cupsGetFd(http=%p, resource=\"%s\", fd=%d)", http,
ef416fc2 70 resource, fd));
71
5a738aea 72 if (!resource || fd < 0)
ef416fc2 73 {
74 if (http)
75 http->error = EINVAL;
76
77 return (HTTP_ERROR);
78 }
79
5a738aea 80 if (!http)
a603edef
MS
81 if ((http = _cupsConnect()) == NULL)
82 return (HTTP_SERVICE_UNAVAILABLE);
5a738aea 83
ef416fc2 84 /*
85 * Then send GET requests to the HTTP server...
86 */
87
757d2cad 88 strlcpy(if_modified_since, httpGetField(http, HTTP_FIELD_IF_MODIFIED_SINCE),
89 sizeof(if_modified_since));
90
ef416fc2 91 do
92 {
93 httpClearFields(http);
94 httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
757d2cad 95 httpSetField(http, HTTP_FIELD_IF_MODIFIED_SINCE, if_modified_since);
ef416fc2 96
97 if (httpGet(http, resource))
98 {
99 if (httpReconnect(http))
100 {
101 status = HTTP_ERROR;
102 break;
103 }
104 else
105 {
106 status = HTTP_UNAUTHORIZED;
107 continue;
108 }
109 }
110
111 while ((status = httpUpdate(http)) == HTTP_CONTINUE);
112
113 if (status == HTTP_UNAUTHORIZED)
114 {
115 /*
116 * Flush any error message...
117 */
118
119 httpFlush(http);
120
121 /*
122 * See if we can do authentication...
123 */
124
125 if (cupsDoAuthentication(http, "GET", resource))
f11a948a
MS
126 {
127 status = HTTP_AUTHORIZATION_CANCELED;
ef416fc2 128 break;
f11a948a 129 }
ef416fc2 130
fa73b229 131 if (httpReconnect(http))
132 {
133 status = HTTP_ERROR;
134 break;
135 }
ef416fc2 136
137 continue;
138 }
139#ifdef HAVE_SSL
140 else if (status == HTTP_UPGRADE_REQUIRED)
141 {
142 /* Flush any error message... */
143 httpFlush(http);
144
145 /* Reconnect... */
fa73b229 146 if (httpReconnect(http))
147 {
148 status = HTTP_ERROR;
149 break;
150 }
ef416fc2 151
152 /* Upgrade with encryption... */
153 httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
154
155 /* Try again, this time with encryption enabled... */
156 continue;
157 }
158#endif /* HAVE_SSL */
159 }
160 while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED);
161
162 /*
163 * See if we actually got the file or an error...
164 */
165
166 if (status == HTTP_OK)
167 {
168 /*
169 * Yes, copy the file...
170 */
171
a4d04587 172 while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0)
ef416fc2 173 write(fd, buffer, bytes);
174 }
175 else
355e94dc
MS
176 {
177 _cupsSetHTTPError(status);
ef416fc2 178 httpFlush(http);
355e94dc 179 }
ef416fc2 180
181 /*
182 * Return the request status...
183 */
184
e07d4801
MS
185 DEBUG_printf(("1cupsGetFd: Returning %d...", status));
186
ef416fc2 187 return (status);
188}
189
190
191/*
192 * 'cupsGetFile()' - Get a file from the server.
193 *
5a738aea 194 * This function returns @code HTTP_OK@ when the file is successfully retrieved.
ef416fc2 195 *
426c6a59 196 * @since CUPS 1.1.20/Mac OS X 10.4@
ef416fc2 197 */
198
ecdc0628 199http_status_t /* O - HTTP status */
568fa3fa 200cupsGetFile(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
ef416fc2 201 const char *resource, /* I - Resource name */
202 const char *filename) /* I - Filename */
203{
204 int fd; /* File descriptor */
205 http_status_t status; /* Status */
206
207
208 /*
209 * Range check input...
210 */
211
212 if (!http || !resource || !filename)
213 {
214 if (http)
215 http->error = EINVAL;
216
217 return (HTTP_ERROR);
218 }
219
220 /*
221 * Create the file...
222 */
223
224 if ((fd = open(filename, O_WRONLY | O_EXCL | O_TRUNC)) < 0)
225 {
226 /*
227 * Couldn't open the file!
228 */
229
230 http->error = errno;
231
232 return (HTTP_ERROR);
233 }
234
235 /*
236 * Get the file...
237 */
238
239 status = cupsGetFd(http, resource, fd);
240
241 /*
242 * If the file couldn't be gotten, then remove the file...
243 */
244
245 close(fd);
246
247 if (status != HTTP_OK)
248 unlink(filename);
249
250 /*
251 * Return the HTTP status code...
252 */
253
254 return (status);
255}
256
257
258/*
259 * 'cupsPutFd()' - Put a file on the server.
260 *
5a738aea
MS
261 * This function returns @code HTTP_CREATED@ when the file is stored
262 * successfully.
ef416fc2 263 *
426c6a59 264 * @since CUPS 1.1.20/Mac OS X 10.4@
ef416fc2 265 */
266
ecdc0628 267http_status_t /* O - HTTP status */
568fa3fa 268cupsPutFd(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
ef416fc2 269 const char *resource, /* I - Resource name */
270 int fd) /* I - File descriptor */
271{
bd7854cb 272 int bytes, /* Number of bytes read */
273 retries; /* Number of retries */
ef416fc2 274 char buffer[8192]; /* Buffer for file */
275 http_status_t status; /* HTTP status from server */
276
277
278 /*
279 * Range check input...
280 */
281
e07d4801 282 DEBUG_printf(("cupsPutFd(http=%p, resource=\"%s\", fd=%d)", http,
ef416fc2 283 resource, fd));
284
5a738aea 285 if (!resource || fd < 0)
ef416fc2 286 {
287 if (http)
288 http->error = EINVAL;
289
290 return (HTTP_ERROR);
291 }
292
5a738aea 293 if (!http)
a603edef
MS
294 if ((http = _cupsConnect()) == NULL)
295 return (HTTP_SERVICE_UNAVAILABLE);
5a738aea 296
ef416fc2 297 /*
298 * Then send PUT requests to the HTTP server...
299 */
300
bd7854cb 301 retries = 0;
302
ef416fc2 303 do
304 {
e07d4801 305 DEBUG_printf(("2cupsPutFd: starting attempt, authstring=\"%s\"...",
ef416fc2 306 http->authstring));
307
308 httpClearFields(http);
309 httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
310 httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, "chunked");
b423cd4c 311 httpSetExpect(http, HTTP_CONTINUE);
ef416fc2 312
313 if (httpPut(http, resource))
314 {
315 if (httpReconnect(http))
316 {
317 status = HTTP_ERROR;
318 break;
319 }
320 else
321 {
322 status = HTTP_UNAUTHORIZED;
323 continue;
324 }
325 }
326
327 /*
b423cd4c 328 * Wait up to 1 second for a 100-continue response...
ef416fc2 329 */
330
b423cd4c 331 if (httpWait(http, 1000))
332 status = httpUpdate(http);
333 else
334 status = HTTP_CONTINUE;
ef416fc2 335
b423cd4c 336 if (status == HTTP_CONTINUE)
337 {
338 /*
339 * Copy the file...
340 */
ef416fc2 341
b423cd4c 342 lseek(fd, 0, SEEK_SET);
343
344 while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
345 if (httpCheck(http))
346 {
347 if ((status = httpUpdate(http)) != HTTP_CONTINUE)
348 break;
349 }
350 else
351 httpWrite2(http, buffer, bytes);
352 }
ef416fc2 353
354 if (status == HTTP_CONTINUE)
355 {
a4d04587 356 httpWrite2(http, buffer, 0);
ef416fc2 357
358 while ((status = httpUpdate(http)) == HTTP_CONTINUE);
359 }
360
bd7854cb 361 if (status == HTTP_ERROR && !retries)
362 {
e07d4801 363 DEBUG_printf(("2cupsPutFd: retry on status %d", status));
bd7854cb 364
365 retries ++;
366
367 /* Flush any error message... */
368 httpFlush(http);
369
370 /* Reconnect... */
371 if (httpReconnect(http))
372 {
373 status = HTTP_ERROR;
374 break;
375 }
376
377 /* Try again... */
378 continue;
379 }
380
e07d4801 381 DEBUG_printf(("2cupsPutFd: status=%d", status));
ef416fc2 382
383 if (status == HTTP_UNAUTHORIZED)
384 {
385 /*
386 * Flush any error message...
387 */
388
389 httpFlush(http);
390
391 /*
392 * See if we can do authentication...
393 */
394
395 if (cupsDoAuthentication(http, "PUT", resource))
f11a948a
MS
396 {
397 status = HTTP_AUTHORIZATION_CANCELED;
ef416fc2 398 break;
f11a948a 399 }
ef416fc2 400
fa73b229 401 if (httpReconnect(http))
402 {
403 status = HTTP_ERROR;
404 break;
405 }
ef416fc2 406
407 continue;
408 }
409#ifdef HAVE_SSL
410 else if (status == HTTP_UPGRADE_REQUIRED)
411 {
412 /* Flush any error message... */
413 httpFlush(http);
414
415 /* Reconnect... */
fa73b229 416 if (httpReconnect(http))
417 {
418 status = HTTP_ERROR;
419 break;
420 }
ef416fc2 421
422 /* Upgrade with encryption... */
423 httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
424
425 /* Try again, this time with encryption enabled... */
426 continue;
427 }
428#endif /* HAVE_SSL */
429 }
bd7854cb 430 while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED ||
431 (status == HTTP_ERROR && retries < 2));
ef416fc2 432
433 /*
434 * See if we actually put the file or an error...
435 */
436
437 if (status != HTTP_CREATED)
355e94dc
MS
438 {
439 _cupsSetHTTPError(status);
ef416fc2 440 httpFlush(http);
355e94dc 441 }
ef416fc2 442
e07d4801
MS
443 DEBUG_printf(("1cupsPutFd: Returning %d...", status));
444
ef416fc2 445 return (status);
446}
447
448
449/*
450 * 'cupsPutFile()' - Put a file on the server.
451 *
5a738aea
MS
452 * This function returns @code HTTP_CREATED@ when the file is stored
453 * successfully.
ef416fc2 454 *
426c6a59 455 * @since CUPS 1.1.20/Mac OS X 10.4@
ef416fc2 456 */
457
ecdc0628 458http_status_t /* O - HTTP status */
568fa3fa 459cupsPutFile(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
ef416fc2 460 const char *resource, /* I - Resource name */
461 const char *filename) /* I - Filename */
462{
463 int fd; /* File descriptor */
464 http_status_t status; /* Status */
465
466
467 /*
468 * Range check input...
469 */
470
471 if (!http || !resource || !filename)
472 {
473 if (http)
474 http->error = EINVAL;
475
476 return (HTTP_ERROR);
477 }
478
479 /*
480 * Open the local file...
481 */
482
483 if ((fd = open(filename, O_RDONLY)) < 0)
484 {
485 /*
486 * Couldn't open the file!
487 */
488
489 http->error = errno;
490
491 return (HTTP_ERROR);
492 }
493
494 /*
495 * Put the file...
496 */
497
498 status = cupsPutFd(http, resource, fd);
499
500 close(fd);
501
502 return (status);
503}
504
505
506/*
75bd9771 507 * End of "$Id: getputfile.c 7359 2008-02-29 19:01:35Z mike $".
ef416fc2 508 */