]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/getputfile.c
Remove all of the Subversion keywords from various source files.
[thirdparty/cups.git] / cups / getputfile.c
CommitLineData
ef416fc2 1/*
7e86f2f6 2 * Get/put file functions for CUPS.
ef416fc2 3 *
7e86f2f6
MS
4 * Copyright 2007-2014 by Apple Inc.
5 * Copyright 1997-2006 by Easy Software Products.
ef416fc2 6 *
7e86f2f6
MS
7 * These coded instructions, statements, and computer programs are the
8 * property of Apple Inc. and are protected by Federal copyright
9 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
10 * which should have been included with this file. If this file is
11 * file is missing or damaged, see the license at "http://www.cups.org/".
ef416fc2 12 *
7e86f2f6 13 * This file is subject to the Apple OS-Developed Software exception.
ef416fc2 14 */
15
16/*
17 * Include necessary headers...
18 */
19
71e16022 20#include "cups-private.h"
ef416fc2 21#include <fcntl.h>
22#include <sys/stat.h>
23#if defined(WIN32) || defined(__EMX__)
24# include <io.h>
25#else
26# include <unistd.h>
27#endif /* WIN32 || __EMX__ */
28
29
30/*
31 * 'cupsGetFd()' - Get a file from the server.
32 *
cb7f98ee 33 * This function returns @code HTTP_STATUS_OK@ when the file is successfully retrieved.
ef416fc2 34 *
f3c17241 35 * @since CUPS 1.1.20/OS X 10.4@
ef416fc2 36 */
37
ecdc0628 38http_status_t /* O - HTTP status */
568fa3fa 39cupsGetFd(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
ef416fc2 40 const char *resource, /* I - Resource name */
41 int fd) /* I - File descriptor */
42{
7e86f2f6 43 ssize_t bytes; /* Number of bytes read */
ef416fc2 44 char buffer[8192]; /* Buffer for file */
45 http_status_t status; /* HTTP status from server */
757d2cad 46 char if_modified_since[HTTP_MAX_VALUE];
47 /* If-Modified-Since header */
ef416fc2 48
49
50 /*
51 * Range check input...
52 */
53
807315e6 54 DEBUG_printf(("cupsGetFd(http=%p, resource=\"%s\", fd=%d)", (void *)http, resource, fd));
ef416fc2 55
5a738aea 56 if (!resource || fd < 0)
ef416fc2 57 {
58 if (http)
59 http->error = EINVAL;
60
cb7f98ee 61 return (HTTP_STATUS_ERROR);
ef416fc2 62 }
63
5a738aea 64 if (!http)
a603edef 65 if ((http = _cupsConnect()) == NULL)
cb7f98ee 66 return (HTTP_STATUS_SERVICE_UNAVAILABLE);
5a738aea 67
ef416fc2 68 /*
69 * Then send GET requests to the HTTP server...
70 */
71
757d2cad 72 strlcpy(if_modified_since, httpGetField(http, HTTP_FIELD_IF_MODIFIED_SINCE),
73 sizeof(if_modified_since));
74
ef416fc2 75 do
76 {
0c4bedc4
MS
77 if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close"))
78 {
79 httpClearFields(http);
80 if (httpReconnect2(http, 30000, NULL))
81 {
82 status = HTTP_STATUS_ERROR;
83 break;
84 }
85 }
86
ef416fc2 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)
7e86f2f6 167 write(fd, buffer, (size_t)bytes);
ef416fc2 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{
7e86f2f6
MS
266 ssize_t bytes; /* Number of bytes read */
267 int 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
807315e6 276 DEBUG_printf(("cupsPutFd(http=%p, resource=\"%s\", fd=%d)", (void *)http, resource, fd));
ef416fc2 277
5a738aea 278 if (!resource || fd < 0)
ef416fc2 279 {
280 if (http)
281 http->error = EINVAL;
282
cb7f98ee 283 return (HTTP_STATUS_ERROR);
ef416fc2 284 }
285
5a738aea 286 if (!http)
a603edef 287 if ((http = _cupsConnect()) == NULL)
cb7f98ee 288 return (HTTP_STATUS_SERVICE_UNAVAILABLE);
5a738aea 289
ef416fc2 290 /*
291 * Then send PUT requests to the HTTP server...
292 */
293
bd7854cb 294 retries = 0;
295
ef416fc2 296 do
297 {
0c4bedc4
MS
298 if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close"))
299 {
300 httpClearFields(http);
301 if (httpReconnect2(http, 30000, NULL))
302 {
303 status = HTTP_STATUS_ERROR;
304 break;
305 }
306 }
307
e07d4801 308 DEBUG_printf(("2cupsPutFd: starting attempt, authstring=\"%s\"...",
ef416fc2 309 http->authstring));
310
311 httpClearFields(http);
312 httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
313 httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, "chunked");
cb7f98ee 314 httpSetExpect(http, HTTP_STATUS_CONTINUE);
ef416fc2 315
316 if (httpPut(http, resource))
317 {
cb7f98ee 318 if (httpReconnect2(http, 30000, NULL))
ef416fc2 319 {
cb7f98ee 320 status = HTTP_STATUS_ERROR;
ef416fc2 321 break;
322 }
323 else
324 {
cb7f98ee 325 status = HTTP_STATUS_UNAUTHORIZED;
ef416fc2 326 continue;
327 }
328 }
329
330 /*
b423cd4c 331 * Wait up to 1 second for a 100-continue response...
ef416fc2 332 */
333
b423cd4c 334 if (httpWait(http, 1000))
335 status = httpUpdate(http);
336 else
cb7f98ee 337 status = HTTP_STATUS_CONTINUE;
ef416fc2 338
cb7f98ee 339 if (status == HTTP_STATUS_CONTINUE)
b423cd4c 340 {
341 /*
342 * Copy the file...
343 */
ef416fc2 344
b423cd4c 345 lseek(fd, 0, SEEK_SET);
346
347 while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
348 if (httpCheck(http))
349 {
cb7f98ee 350 if ((status = httpUpdate(http)) != HTTP_STATUS_CONTINUE)
b423cd4c 351 break;
352 }
353 else
7e86f2f6 354 httpWrite2(http, buffer, (size_t)bytes);
b423cd4c 355 }
ef416fc2 356
cb7f98ee 357 if (status == HTTP_STATUS_CONTINUE)
ef416fc2 358 {
a4d04587 359 httpWrite2(http, buffer, 0);
ef416fc2 360
cb7f98ee 361 while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE);
ef416fc2 362 }
363
cb7f98ee 364 if (status == HTTP_STATUS_ERROR && !retries)
bd7854cb 365 {
e07d4801 366 DEBUG_printf(("2cupsPutFd: retry on status %d", status));
bd7854cb 367
368 retries ++;
369
370 /* Flush any error message... */
371 httpFlush(http);
372
373 /* Reconnect... */
cb7f98ee 374 if (httpReconnect2(http, 30000, NULL))
bd7854cb 375 {
cb7f98ee 376 status = HTTP_STATUS_ERROR;
bd7854cb 377 break;
378 }
379
380 /* Try again... */
381 continue;
382 }
383
e07d4801 384 DEBUG_printf(("2cupsPutFd: status=%d", status));
ef416fc2 385
cb7f98ee 386 if (status == HTTP_STATUS_UNAUTHORIZED)
ef416fc2 387 {
388 /*
389 * Flush any error message...
390 */
391
392 httpFlush(http);
393
394 /*
395 * See if we can do authentication...
396 */
397
398 if (cupsDoAuthentication(http, "PUT", resource))
f11a948a 399 {
cb7f98ee 400 status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
ef416fc2 401 break;
f11a948a 402 }
ef416fc2 403
cb7f98ee 404 if (httpReconnect2(http, 30000, NULL))
fa73b229 405 {
cb7f98ee 406 status = HTTP_STATUS_ERROR;
fa73b229 407 break;
408 }
ef416fc2 409
410 continue;
411 }
412#ifdef HAVE_SSL
cb7f98ee 413 else if (status == HTTP_STATUS_UPGRADE_REQUIRED)
ef416fc2 414 {
415 /* Flush any error message... */
416 httpFlush(http);
417
418 /* Reconnect... */
cb7f98ee 419 if (httpReconnect2(http, 30000, NULL))
fa73b229 420 {
cb7f98ee 421 status = HTTP_STATUS_ERROR;
fa73b229 422 break;
423 }
ef416fc2 424
425 /* Upgrade with encryption... */
cb7f98ee 426 httpEncryption(http, HTTP_ENCRYPTION_REQUIRED);
ef416fc2 427
428 /* Try again, this time with encryption enabled... */
429 continue;
430 }
431#endif /* HAVE_SSL */
432 }
cb7f98ee
MS
433 while (status == HTTP_STATUS_UNAUTHORIZED || status == HTTP_STATUS_UPGRADE_REQUIRED ||
434 (status == HTTP_STATUS_ERROR && retries < 2));
ef416fc2 435
436 /*
437 * See if we actually put the file or an error...
438 */
439
cb7f98ee 440 if (status != HTTP_STATUS_CREATED)
355e94dc
MS
441 {
442 _cupsSetHTTPError(status);
ef416fc2 443 httpFlush(http);
355e94dc 444 }
ef416fc2 445
e07d4801
MS
446 DEBUG_printf(("1cupsPutFd: Returning %d...", status));
447
ef416fc2 448 return (status);
449}
450
451
452/*
453 * 'cupsPutFile()' - Put a file on the server.
454 *
5a738aea
MS
455 * This function returns @code HTTP_CREATED@ when the file is stored
456 * successfully.
ef416fc2 457 *
f3c17241 458 * @since CUPS 1.1.20/OS X 10.4@
ef416fc2 459 */
460
ecdc0628 461http_status_t /* O - HTTP status */
568fa3fa 462cupsPutFile(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
ef416fc2 463 const char *resource, /* I - Resource name */
464 const char *filename) /* I - Filename */
465{
466 int fd; /* File descriptor */
467 http_status_t status; /* Status */
468
469
470 /*
471 * Range check input...
472 */
473
474 if (!http || !resource || !filename)
475 {
476 if (http)
477 http->error = EINVAL;
478
cb7f98ee 479 return (HTTP_STATUS_ERROR);
ef416fc2 480 }
481
482 /*
483 * Open the local file...
484 */
485
486 if ((fd = open(filename, O_RDONLY)) < 0)
487 {
488 /*
489 * Couldn't open the file!
490 */
491
492 http->error = errno;
493
cb7f98ee 494 return (HTTP_STATUS_ERROR);
ef416fc2 495 }
496
497 /*
498 * Put the file...
499 */
500
501 status = cupsPutFd(http, resource, fd);
502
503 close(fd);
504
505 return (status);
506}