]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/getputfile.c
Merge changes from CUPS 1.4svn-r8540.
[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))
126 break;
127
fa73b229 128 if (httpReconnect(http))
129 {
130 status = HTTP_ERROR;
131 break;
132 }
ef416fc2 133
134 continue;
135 }
136#ifdef HAVE_SSL
137 else if (status == HTTP_UPGRADE_REQUIRED)
138 {
139 /* Flush any error message... */
140 httpFlush(http);
141
142 /* Reconnect... */
fa73b229 143 if (httpReconnect(http))
144 {
145 status = HTTP_ERROR;
146 break;
147 }
ef416fc2 148
149 /* Upgrade with encryption... */
150 httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
151
152 /* Try again, this time with encryption enabled... */
153 continue;
154 }
155#endif /* HAVE_SSL */
156 }
157 while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED);
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
a4d04587 169 while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0)
ef416fc2 170 write(fd, buffer, bytes);
171 }
172 else
355e94dc
MS
173 {
174 _cupsSetHTTPError(status);
ef416fc2 175 httpFlush(http);
355e94dc 176 }
ef416fc2 177
178 /*
179 * Return the request status...
180 */
181
e07d4801
MS
182 DEBUG_printf(("1cupsGetFd: Returning %d...", status));
183
ef416fc2 184 return (status);
185}
186
187
188/*
189 * 'cupsGetFile()' - Get a file from the server.
190 *
5a738aea 191 * This function returns @code HTTP_OK@ when the file is successfully retrieved.
ef416fc2 192 *
426c6a59 193 * @since CUPS 1.1.20/Mac OS X 10.4@
ef416fc2 194 */
195
ecdc0628 196http_status_t /* O - HTTP status */
568fa3fa 197cupsGetFile(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
ef416fc2 198 const char *resource, /* I - Resource name */
199 const char *filename) /* I - Filename */
200{
201 int fd; /* File descriptor */
202 http_status_t status; /* Status */
203
204
205 /*
206 * Range check input...
207 */
208
209 if (!http || !resource || !filename)
210 {
211 if (http)
212 http->error = EINVAL;
213
214 return (HTTP_ERROR);
215 }
216
217 /*
218 * Create the file...
219 */
220
221 if ((fd = open(filename, O_WRONLY | O_EXCL | O_TRUNC)) < 0)
222 {
223 /*
224 * Couldn't open the file!
225 */
226
227 http->error = errno;
228
229 return (HTTP_ERROR);
230 }
231
232 /*
233 * Get the file...
234 */
235
236 status = cupsGetFd(http, resource, fd);
237
238 /*
239 * If the file couldn't be gotten, then remove the file...
240 */
241
242 close(fd);
243
244 if (status != HTTP_OK)
245 unlink(filename);
246
247 /*
248 * Return the HTTP status code...
249 */
250
251 return (status);
252}
253
254
255/*
256 * 'cupsPutFd()' - Put a file on the server.
257 *
5a738aea
MS
258 * This function returns @code HTTP_CREATED@ when the file is stored
259 * successfully.
ef416fc2 260 *
426c6a59 261 * @since CUPS 1.1.20/Mac OS X 10.4@
ef416fc2 262 */
263
ecdc0628 264http_status_t /* O - HTTP status */
568fa3fa 265cupsPutFd(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
ef416fc2 266 const char *resource, /* I - Resource name */
267 int fd) /* I - File descriptor */
268{
bd7854cb 269 int bytes, /* Number of bytes read */
270 retries; /* Number of retries */
ef416fc2 271 char buffer[8192]; /* Buffer for file */
272 http_status_t status; /* HTTP status from server */
273
274
275 /*
276 * Range check input...
277 */
278
e07d4801 279 DEBUG_printf(("cupsPutFd(http=%p, resource=\"%s\", fd=%d)", http,
ef416fc2 280 resource, fd));
281
5a738aea 282 if (!resource || fd < 0)
ef416fc2 283 {
284 if (http)
285 http->error = EINVAL;
286
287 return (HTTP_ERROR);
288 }
289
5a738aea 290 if (!http)
a603edef
MS
291 if ((http = _cupsConnect()) == NULL)
292 return (HTTP_SERVICE_UNAVAILABLE);
5a738aea 293
ef416fc2 294 /*
295 * Then send PUT requests to the HTTP server...
296 */
297
bd7854cb 298 retries = 0;
299
ef416fc2 300 do
301 {
e07d4801 302 DEBUG_printf(("2cupsPutFd: starting attempt, authstring=\"%s\"...",
ef416fc2 303 http->authstring));
304
305 httpClearFields(http);
306 httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
307 httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, "chunked");
b423cd4c 308 httpSetExpect(http, HTTP_CONTINUE);
ef416fc2 309
310 if (httpPut(http, resource))
311 {
312 if (httpReconnect(http))
313 {
314 status = HTTP_ERROR;
315 break;
316 }
317 else
318 {
319 status = HTTP_UNAUTHORIZED;
320 continue;
321 }
322 }
323
324 /*
b423cd4c 325 * Wait up to 1 second for a 100-continue response...
ef416fc2 326 */
327
b423cd4c 328 if (httpWait(http, 1000))
329 status = httpUpdate(http);
330 else
331 status = HTTP_CONTINUE;
ef416fc2 332
b423cd4c 333 if (status == HTTP_CONTINUE)
334 {
335 /*
336 * Copy the file...
337 */
ef416fc2 338
b423cd4c 339 lseek(fd, 0, SEEK_SET);
340
341 while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
342 if (httpCheck(http))
343 {
344 if ((status = httpUpdate(http)) != HTTP_CONTINUE)
345 break;
346 }
347 else
348 httpWrite2(http, buffer, bytes);
349 }
ef416fc2 350
351 if (status == HTTP_CONTINUE)
352 {
a4d04587 353 httpWrite2(http, buffer, 0);
ef416fc2 354
355 while ((status = httpUpdate(http)) == HTTP_CONTINUE);
356 }
357
bd7854cb 358 if (status == HTTP_ERROR && !retries)
359 {
e07d4801 360 DEBUG_printf(("2cupsPutFd: retry on status %d", status));
bd7854cb 361
362 retries ++;
363
364 /* Flush any error message... */
365 httpFlush(http);
366
367 /* Reconnect... */
368 if (httpReconnect(http))
369 {
370 status = HTTP_ERROR;
371 break;
372 }
373
374 /* Try again... */
375 continue;
376 }
377
e07d4801 378 DEBUG_printf(("2cupsPutFd: status=%d", status));
ef416fc2 379
380 if (status == HTTP_UNAUTHORIZED)
381 {
382 /*
383 * Flush any error message...
384 */
385
386 httpFlush(http);
387
388 /*
389 * See if we can do authentication...
390 */
391
392 if (cupsDoAuthentication(http, "PUT", resource))
393 break;
394
fa73b229 395 if (httpReconnect(http))
396 {
397 status = HTTP_ERROR;
398 break;
399 }
ef416fc2 400
401 continue;
402 }
403#ifdef HAVE_SSL
404 else if (status == HTTP_UPGRADE_REQUIRED)
405 {
406 /* Flush any error message... */
407 httpFlush(http);
408
409 /* Reconnect... */
fa73b229 410 if (httpReconnect(http))
411 {
412 status = HTTP_ERROR;
413 break;
414 }
ef416fc2 415
416 /* Upgrade with encryption... */
417 httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
418
419 /* Try again, this time with encryption enabled... */
420 continue;
421 }
422#endif /* HAVE_SSL */
423 }
bd7854cb 424 while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED ||
425 (status == HTTP_ERROR && retries < 2));
ef416fc2 426
427 /*
428 * See if we actually put the file or an error...
429 */
430
431 if (status != HTTP_CREATED)
355e94dc
MS
432 {
433 _cupsSetHTTPError(status);
ef416fc2 434 httpFlush(http);
355e94dc 435 }
ef416fc2 436
e07d4801
MS
437 DEBUG_printf(("1cupsPutFd: Returning %d...", status));
438
ef416fc2 439 return (status);
440}
441
442
443/*
444 * 'cupsPutFile()' - Put a file on the server.
445 *
5a738aea
MS
446 * This function returns @code HTTP_CREATED@ when the file is stored
447 * successfully.
ef416fc2 448 *
426c6a59 449 * @since CUPS 1.1.20/Mac OS X 10.4@
ef416fc2 450 */
451
ecdc0628 452http_status_t /* O - HTTP status */
568fa3fa 453cupsPutFile(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
ef416fc2 454 const char *resource, /* I - Resource name */
455 const char *filename) /* I - Filename */
456{
457 int fd; /* File descriptor */
458 http_status_t status; /* Status */
459
460
461 /*
462 * Range check input...
463 */
464
465 if (!http || !resource || !filename)
466 {
467 if (http)
468 http->error = EINVAL;
469
470 return (HTTP_ERROR);
471 }
472
473 /*
474 * Open the local file...
475 */
476
477 if ((fd = open(filename, O_RDONLY)) < 0)
478 {
479 /*
480 * Couldn't open the file!
481 */
482
483 http->error = errno;
484
485 return (HTTP_ERROR);
486 }
487
488 /*
489 * Put the file...
490 */
491
492 status = cupsPutFd(http, resource, fd);
493
494 close(fd);
495
496 return (status);
497}
498
499
500/*
75bd9771 501 * End of "$Id: getputfile.c 7359 2008-02-29 19:01:35Z mike $".
ef416fc2 502 */