]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/getputfile.c
Update svn:keyword properties.
[thirdparty/cups.git] / cups / getputfile.c
CommitLineData
ef416fc2 1/*
f2d18633 2 * "$Id$"
ef416fc2 3 *
71e16022 4 * Get/put file functions for CUPS.
ef416fc2 5 *
cb7f98ee 6 * Copyright 2007-2013 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
71e16022 29#include "cups-private.h"
ef416fc2 30#include <fcntl.h>
31#include <sys/stat.h>
32#if defined(WIN32) || defined(__EMX__)
33# include <io.h>
34#else
35# include <unistd.h>
36#endif /* WIN32 || __EMX__ */
37
38
39/*
40 * 'cupsGetFd()' - Get a file from the server.
41 *
cb7f98ee 42 * This function returns @code HTTP_STATUS_OK@ when the file is successfully retrieved.
ef416fc2 43 *
f3c17241 44 * @since CUPS 1.1.20/OS X 10.4@
ef416fc2 45 */
46
ecdc0628 47http_status_t /* O - HTTP status */
568fa3fa 48cupsGetFd(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
ef416fc2 49 const char *resource, /* I - Resource name */
50 int fd) /* I - File descriptor */
51{
52 int bytes; /* Number of bytes read */
53 char buffer[8192]; /* Buffer for file */
54 http_status_t status; /* HTTP status from server */
757d2cad 55 char if_modified_since[HTTP_MAX_VALUE];
56 /* If-Modified-Since header */
ef416fc2 57
58
59 /*
60 * Range check input...
61 */
62
e07d4801 63 DEBUG_printf(("cupsGetFd(http=%p, resource=\"%s\", fd=%d)", http,
ef416fc2 64 resource, fd));
65
5a738aea 66 if (!resource || fd < 0)
ef416fc2 67 {
68 if (http)
69 http->error = EINVAL;
70
cb7f98ee 71 return (HTTP_STATUS_ERROR);
ef416fc2 72 }
73
5a738aea 74 if (!http)
a603edef 75 if ((http = _cupsConnect()) == NULL)
cb7f98ee 76 return (HTTP_STATUS_SERVICE_UNAVAILABLE);
5a738aea 77
ef416fc2 78 /*
79 * Then send GET requests to the HTTP server...
80 */
81
757d2cad 82 strlcpy(if_modified_since, httpGetField(http, HTTP_FIELD_IF_MODIFIED_SINCE),
83 sizeof(if_modified_since));
84
ef416fc2 85 do
86 {
87 httpClearFields(http);
88 httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
757d2cad 89 httpSetField(http, HTTP_FIELD_IF_MODIFIED_SINCE, if_modified_since);
ef416fc2 90
91 if (httpGet(http, resource))
92 {
cb7f98ee 93 if (httpReconnect2(http, 30000, NULL))
ef416fc2 94 {
cb7f98ee 95 status = HTTP_STATUS_ERROR;
ef416fc2 96 break;
97 }
98 else
99 {
cb7f98ee 100 status = HTTP_STATUS_UNAUTHORIZED;
ef416fc2 101 continue;
102 }
103 }
104
cb7f98ee 105 while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE);
ef416fc2 106
cb7f98ee 107 if (status == HTTP_STATUS_UNAUTHORIZED)
ef416fc2 108 {
109 /*
110 * Flush any error message...
111 */
112
113 httpFlush(http);
114
115 /*
116 * See if we can do authentication...
117 */
118
119 if (cupsDoAuthentication(http, "GET", resource))
f11a948a 120 {
cb7f98ee 121 status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
ef416fc2 122 break;
f11a948a 123 }
ef416fc2 124
cb7f98ee 125 if (httpReconnect2(http, 30000, NULL))
fa73b229 126 {
cb7f98ee 127 status = HTTP_STATUS_ERROR;
fa73b229 128 break;
129 }
ef416fc2 130
131 continue;
132 }
133#ifdef HAVE_SSL
cb7f98ee 134 else if (status == HTTP_STATUS_UPGRADE_REQUIRED)
ef416fc2 135 {
136 /* Flush any error message... */
137 httpFlush(http);
138
139 /* Reconnect... */
cb7f98ee 140 if (httpReconnect2(http, 30000, NULL))
fa73b229 141 {
cb7f98ee 142 status = HTTP_STATUS_ERROR;
fa73b229 143 break;
144 }
ef416fc2 145
146 /* Upgrade with encryption... */
cb7f98ee 147 httpEncryption(http, HTTP_ENCRYPTION_REQUIRED);
ef416fc2 148
149 /* Try again, this time with encryption enabled... */
150 continue;
151 }
152#endif /* HAVE_SSL */
153 }
cb7f98ee 154 while (status == HTTP_STATUS_UNAUTHORIZED || status == HTTP_STATUS_UPGRADE_REQUIRED);
ef416fc2 155
156 /*
157 * See if we actually got the file or an error...
158 */
159
cb7f98ee 160 if (status == HTTP_STATUS_OK)
ef416fc2 161 {
162 /*
163 * Yes, copy the file...
164 */
165
a4d04587 166 while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0)
ef416fc2 167 write(fd, buffer, bytes);
168 }
169 else
355e94dc
MS
170 {
171 _cupsSetHTTPError(status);
ef416fc2 172 httpFlush(http);
355e94dc 173 }
ef416fc2 174
175 /*
176 * Return the request status...
177 */
178
e07d4801
MS
179 DEBUG_printf(("1cupsGetFd: Returning %d...", status));
180
ef416fc2 181 return (status);
182}
183
184
185/*
186 * 'cupsGetFile()' - Get a file from the server.
187 *
cb7f98ee 188 * This function returns @code HTTP_STATUS_OK@ when the file is successfully retrieved.
ef416fc2 189 *
f3c17241 190 * @since CUPS 1.1.20/OS X 10.4@
ef416fc2 191 */
192
ecdc0628 193http_status_t /* O - HTTP status */
568fa3fa 194cupsGetFile(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
ef416fc2 195 const char *resource, /* I - Resource name */
196 const char *filename) /* I - Filename */
197{
198 int fd; /* File descriptor */
199 http_status_t status; /* Status */
200
201
202 /*
203 * Range check input...
204 */
205
206 if (!http || !resource || !filename)
207 {
208 if (http)
209 http->error = EINVAL;
210
cb7f98ee 211 return (HTTP_STATUS_ERROR);
ef416fc2 212 }
213
214 /*
215 * Create the file...
216 */
217
218 if ((fd = open(filename, O_WRONLY | O_EXCL | O_TRUNC)) < 0)
219 {
220 /*
221 * Couldn't open the file!
222 */
223
224 http->error = errno;
225
cb7f98ee 226 return (HTTP_STATUS_ERROR);
ef416fc2 227 }
228
229 /*
230 * Get the file...
231 */
232
233 status = cupsGetFd(http, resource, fd);
234
235 /*
236 * If the file couldn't be gotten, then remove the file...
237 */
238
239 close(fd);
240
cb7f98ee 241 if (status != HTTP_STATUS_OK)
ef416fc2 242 unlink(filename);
243
244 /*
245 * Return the HTTP status code...
246 */
247
248 return (status);
249}
250
251
252/*
253 * 'cupsPutFd()' - Put a file on the server.
254 *
cb7f98ee 255 * This function returns @code HTTP_STATUS_CREATED@ when the file is stored
5a738aea 256 * successfully.
ef416fc2 257 *
f3c17241 258 * @since CUPS 1.1.20/OS X 10.4@
ef416fc2 259 */
260
ecdc0628 261http_status_t /* O - HTTP status */
568fa3fa 262cupsPutFd(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
ef416fc2 263 const char *resource, /* I - Resource name */
264 int fd) /* I - File descriptor */
265{
bd7854cb 266 int bytes, /* Number of bytes read */
267 retries; /* Number of retries */
ef416fc2 268 char buffer[8192]; /* Buffer for file */
269 http_status_t status; /* HTTP status from server */
270
271
272 /*
273 * Range check input...
274 */
275
e07d4801 276 DEBUG_printf(("cupsPutFd(http=%p, resource=\"%s\", fd=%d)", http,
ef416fc2 277 resource, fd));
278
5a738aea 279 if (!resource || fd < 0)
ef416fc2 280 {
281 if (http)
282 http->error = EINVAL;
283
cb7f98ee 284 return (HTTP_STATUS_ERROR);
ef416fc2 285 }
286
5a738aea 287 if (!http)
a603edef 288 if ((http = _cupsConnect()) == NULL)
cb7f98ee 289 return (HTTP_STATUS_SERVICE_UNAVAILABLE);
5a738aea 290
ef416fc2 291 /*
292 * Then send PUT requests to the HTTP server...
293 */
294
bd7854cb 295 retries = 0;
296
ef416fc2 297 do
298 {
e07d4801 299 DEBUG_printf(("2cupsPutFd: starting attempt, authstring=\"%s\"...",
ef416fc2 300 http->authstring));
301
302 httpClearFields(http);
303 httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
304 httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, "chunked");
cb7f98ee 305 httpSetExpect(http, HTTP_STATUS_CONTINUE);
ef416fc2 306
307 if (httpPut(http, resource))
308 {
cb7f98ee 309 if (httpReconnect2(http, 30000, NULL))
ef416fc2 310 {
cb7f98ee 311 status = HTTP_STATUS_ERROR;
ef416fc2 312 break;
313 }
314 else
315 {
cb7f98ee 316 status = HTTP_STATUS_UNAUTHORIZED;
ef416fc2 317 continue;
318 }
319 }
320
321 /*
b423cd4c 322 * Wait up to 1 second for a 100-continue response...
ef416fc2 323 */
324
b423cd4c 325 if (httpWait(http, 1000))
326 status = httpUpdate(http);
327 else
cb7f98ee 328 status = HTTP_STATUS_CONTINUE;
ef416fc2 329
cb7f98ee 330 if (status == HTTP_STATUS_CONTINUE)
b423cd4c 331 {
332 /*
333 * Copy the file...
334 */
ef416fc2 335
b423cd4c 336 lseek(fd, 0, SEEK_SET);
337
338 while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
339 if (httpCheck(http))
340 {
cb7f98ee 341 if ((status = httpUpdate(http)) != HTTP_STATUS_CONTINUE)
b423cd4c 342 break;
343 }
344 else
345 httpWrite2(http, buffer, bytes);
346 }
ef416fc2 347
cb7f98ee 348 if (status == HTTP_STATUS_CONTINUE)
ef416fc2 349 {
a4d04587 350 httpWrite2(http, buffer, 0);
ef416fc2 351
cb7f98ee 352 while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE);
ef416fc2 353 }
354
cb7f98ee 355 if (status == HTTP_STATUS_ERROR && !retries)
bd7854cb 356 {
e07d4801 357 DEBUG_printf(("2cupsPutFd: retry on status %d", status));
bd7854cb 358
359 retries ++;
360
361 /* Flush any error message... */
362 httpFlush(http);
363
364 /* Reconnect... */
cb7f98ee 365 if (httpReconnect2(http, 30000, NULL))
bd7854cb 366 {
cb7f98ee 367 status = HTTP_STATUS_ERROR;
bd7854cb 368 break;
369 }
370
371 /* Try again... */
372 continue;
373 }
374
e07d4801 375 DEBUG_printf(("2cupsPutFd: status=%d", status));
ef416fc2 376
cb7f98ee 377 if (status == HTTP_STATUS_UNAUTHORIZED)
ef416fc2 378 {
379 /*
380 * Flush any error message...
381 */
382
383 httpFlush(http);
384
385 /*
386 * See if we can do authentication...
387 */
388
389 if (cupsDoAuthentication(http, "PUT", resource))
f11a948a 390 {
cb7f98ee 391 status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
ef416fc2 392 break;
f11a948a 393 }
ef416fc2 394
cb7f98ee 395 if (httpReconnect2(http, 30000, NULL))
fa73b229 396 {
cb7f98ee 397 status = HTTP_STATUS_ERROR;
fa73b229 398 break;
399 }
ef416fc2 400
401 continue;
402 }
403#ifdef HAVE_SSL
cb7f98ee 404 else if (status == HTTP_STATUS_UPGRADE_REQUIRED)
ef416fc2 405 {
406 /* Flush any error message... */
407 httpFlush(http);
408
409 /* Reconnect... */
cb7f98ee 410 if (httpReconnect2(http, 30000, NULL))
fa73b229 411 {
cb7f98ee 412 status = HTTP_STATUS_ERROR;
fa73b229 413 break;
414 }
ef416fc2 415
416 /* Upgrade with encryption... */
cb7f98ee 417 httpEncryption(http, HTTP_ENCRYPTION_REQUIRED);
ef416fc2 418
419 /* Try again, this time with encryption enabled... */
420 continue;
421 }
422#endif /* HAVE_SSL */
423 }
cb7f98ee
MS
424 while (status == HTTP_STATUS_UNAUTHORIZED || status == HTTP_STATUS_UPGRADE_REQUIRED ||
425 (status == HTTP_STATUS_ERROR && retries < 2));
ef416fc2 426
427 /*
428 * See if we actually put the file or an error...
429 */
430
cb7f98ee 431 if (status != HTTP_STATUS_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 *
f3c17241 449 * @since CUPS 1.1.20/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
cb7f98ee 470 return (HTTP_STATUS_ERROR);
ef416fc2 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
cb7f98ee 485 return (HTTP_STATUS_ERROR);
ef416fc2 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/*
f2d18633 501 * End of "$Id$".
ef416fc2 502 */