]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/getputfile.c
Merge pull request #4788 from leoarnold/mailmap
[thirdparty/cups.git] / cups / getputfile.c
CommitLineData
ef416fc2 1/*
f2d18633 2 * "$Id$"
ef416fc2 3 *
7e86f2f6 4 * Get/put file functions for CUPS.
ef416fc2 5 *
7e86f2f6
MS
6 * Copyright 2007-2014 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products.
ef416fc2 8 *
7e86f2f6
MS
9 * These coded instructions, statements, and computer programs are the
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 *
7e86f2f6 15 * This file is subject to the Apple OS-Developed Software exception.
ef416fc2 16 */
17
18/*
19 * Include necessary headers...
20 */
21
71e16022 22#include "cups-private.h"
ef416fc2 23#include <fcntl.h>
24#include <sys/stat.h>
25#if defined(WIN32) || defined(__EMX__)
26# include <io.h>
27#else
28# include <unistd.h>
29#endif /* WIN32 || __EMX__ */
30
31
32/*
33 * 'cupsGetFd()' - Get a file from the server.
34 *
cb7f98ee 35 * This function returns @code HTTP_STATUS_OK@ when the file is successfully retrieved.
ef416fc2 36 *
f3c17241 37 * @since CUPS 1.1.20/OS X 10.4@
ef416fc2 38 */
39
ecdc0628 40http_status_t /* O - HTTP status */
568fa3fa 41cupsGetFd(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
ef416fc2 42 const char *resource, /* I - Resource name */
43 int fd) /* I - File descriptor */
44{
7e86f2f6 45 ssize_t bytes; /* Number of bytes read */
ef416fc2 46 char buffer[8192]; /* Buffer for file */
47 http_status_t status; /* HTTP status from server */
757d2cad 48 char if_modified_since[HTTP_MAX_VALUE];
49 /* If-Modified-Since header */
ef416fc2 50
51
52 /*
53 * Range check input...
54 */
55
e07d4801 56 DEBUG_printf(("cupsGetFd(http=%p, resource=\"%s\", fd=%d)", http,
ef416fc2 57 resource, fd));
58
5a738aea 59 if (!resource || fd < 0)
ef416fc2 60 {
61 if (http)
62 http->error = EINVAL;
63
cb7f98ee 64 return (HTTP_STATUS_ERROR);
ef416fc2 65 }
66
5a738aea 67 if (!http)
a603edef 68 if ((http = _cupsConnect()) == NULL)
cb7f98ee 69 return (HTTP_STATUS_SERVICE_UNAVAILABLE);
5a738aea 70
ef416fc2 71 /*
72 * Then send GET requests to the HTTP server...
73 */
74
757d2cad 75 strlcpy(if_modified_since, httpGetField(http, HTTP_FIELD_IF_MODIFIED_SINCE),
76 sizeof(if_modified_since));
77
ef416fc2 78 do
79 {
0c4bedc4
MS
80 if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close"))
81 {
82 httpClearFields(http);
83 if (httpReconnect2(http, 30000, NULL))
84 {
85 status = HTTP_STATUS_ERROR;
86 break;
87 }
88 }
89
ef416fc2 90 httpClearFields(http);
91 httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
757d2cad 92 httpSetField(http, HTTP_FIELD_IF_MODIFIED_SINCE, if_modified_since);
ef416fc2 93
94 if (httpGet(http, resource))
95 {
cb7f98ee 96 if (httpReconnect2(http, 30000, NULL))
ef416fc2 97 {
cb7f98ee 98 status = HTTP_STATUS_ERROR;
ef416fc2 99 break;
100 }
101 else
102 {
cb7f98ee 103 status = HTTP_STATUS_UNAUTHORIZED;
ef416fc2 104 continue;
105 }
106 }
107
cb7f98ee 108 while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE);
ef416fc2 109
cb7f98ee 110 if (status == HTTP_STATUS_UNAUTHORIZED)
ef416fc2 111 {
112 /*
113 * Flush any error message...
114 */
115
116 httpFlush(http);
117
118 /*
119 * See if we can do authentication...
120 */
121
122 if (cupsDoAuthentication(http, "GET", resource))
f11a948a 123 {
cb7f98ee 124 status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
ef416fc2 125 break;
f11a948a 126 }
ef416fc2 127
cb7f98ee 128 if (httpReconnect2(http, 30000, NULL))
fa73b229 129 {
cb7f98ee 130 status = HTTP_STATUS_ERROR;
fa73b229 131 break;
132 }
ef416fc2 133
134 continue;
135 }
136#ifdef HAVE_SSL
cb7f98ee 137 else if (status == HTTP_STATUS_UPGRADE_REQUIRED)
ef416fc2 138 {
139 /* Flush any error message... */
140 httpFlush(http);
141
142 /* Reconnect... */
cb7f98ee 143 if (httpReconnect2(http, 30000, NULL))
fa73b229 144 {
cb7f98ee 145 status = HTTP_STATUS_ERROR;
fa73b229 146 break;
147 }
ef416fc2 148
149 /* Upgrade with encryption... */
cb7f98ee 150 httpEncryption(http, HTTP_ENCRYPTION_REQUIRED);
ef416fc2 151
152 /* Try again, this time with encryption enabled... */
153 continue;
154 }
155#endif /* HAVE_SSL */
156 }
cb7f98ee 157 while (status == HTTP_STATUS_UNAUTHORIZED || status == HTTP_STATUS_UPGRADE_REQUIRED);
ef416fc2 158
159 /*
160 * See if we actually got the file or an error...
161 */
162
cb7f98ee 163 if (status == HTTP_STATUS_OK)
ef416fc2 164 {
165 /*
166 * Yes, copy the file...
167 */
168
a4d04587 169 while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0)
7e86f2f6 170 write(fd, buffer, (size_t)bytes);
ef416fc2 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 *
cb7f98ee 191 * This function returns @code HTTP_STATUS_OK@ when the file is successfully retrieved.
ef416fc2 192 *
f3c17241 193 * @since CUPS 1.1.20/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
cb7f98ee 214 return (HTTP_STATUS_ERROR);
ef416fc2 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
cb7f98ee 229 return (HTTP_STATUS_ERROR);
ef416fc2 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
cb7f98ee 244 if (status != HTTP_STATUS_OK)
ef416fc2 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 *
cb7f98ee 258 * This function returns @code HTTP_STATUS_CREATED@ when the file is stored
5a738aea 259 * successfully.
ef416fc2 260 *
f3c17241 261 * @since CUPS 1.1.20/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{
7e86f2f6
MS
269 ssize_t bytes; /* Number of bytes read */
270 int 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
cb7f98ee 287 return (HTTP_STATUS_ERROR);
ef416fc2 288 }
289
5a738aea 290 if (!http)
a603edef 291 if ((http = _cupsConnect()) == NULL)
cb7f98ee 292 return (HTTP_STATUS_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 {
0c4bedc4
MS
302 if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close"))
303 {
304 httpClearFields(http);
305 if (httpReconnect2(http, 30000, NULL))
306 {
307 status = HTTP_STATUS_ERROR;
308 break;
309 }
310 }
311
e07d4801 312 DEBUG_printf(("2cupsPutFd: starting attempt, authstring=\"%s\"...",
ef416fc2 313 http->authstring));
314
315 httpClearFields(http);
316 httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
317 httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, "chunked");
cb7f98ee 318 httpSetExpect(http, HTTP_STATUS_CONTINUE);
ef416fc2 319
320 if (httpPut(http, resource))
321 {
cb7f98ee 322 if (httpReconnect2(http, 30000, NULL))
ef416fc2 323 {
cb7f98ee 324 status = HTTP_STATUS_ERROR;
ef416fc2 325 break;
326 }
327 else
328 {
cb7f98ee 329 status = HTTP_STATUS_UNAUTHORIZED;
ef416fc2 330 continue;
331 }
332 }
333
334 /*
b423cd4c 335 * Wait up to 1 second for a 100-continue response...
ef416fc2 336 */
337
b423cd4c 338 if (httpWait(http, 1000))
339 status = httpUpdate(http);
340 else
cb7f98ee 341 status = HTTP_STATUS_CONTINUE;
ef416fc2 342
cb7f98ee 343 if (status == HTTP_STATUS_CONTINUE)
b423cd4c 344 {
345 /*
346 * Copy the file...
347 */
ef416fc2 348
b423cd4c 349 lseek(fd, 0, SEEK_SET);
350
351 while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
352 if (httpCheck(http))
353 {
cb7f98ee 354 if ((status = httpUpdate(http)) != HTTP_STATUS_CONTINUE)
b423cd4c 355 break;
356 }
357 else
7e86f2f6 358 httpWrite2(http, buffer, (size_t)bytes);
b423cd4c 359 }
ef416fc2 360
cb7f98ee 361 if (status == HTTP_STATUS_CONTINUE)
ef416fc2 362 {
a4d04587 363 httpWrite2(http, buffer, 0);
ef416fc2 364
cb7f98ee 365 while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE);
ef416fc2 366 }
367
cb7f98ee 368 if (status == HTTP_STATUS_ERROR && !retries)
bd7854cb 369 {
e07d4801 370 DEBUG_printf(("2cupsPutFd: retry on status %d", status));
bd7854cb 371
372 retries ++;
373
374 /* Flush any error message... */
375 httpFlush(http);
376
377 /* Reconnect... */
cb7f98ee 378 if (httpReconnect2(http, 30000, NULL))
bd7854cb 379 {
cb7f98ee 380 status = HTTP_STATUS_ERROR;
bd7854cb 381 break;
382 }
383
384 /* Try again... */
385 continue;
386 }
387
e07d4801 388 DEBUG_printf(("2cupsPutFd: status=%d", status));
ef416fc2 389
cb7f98ee 390 if (status == HTTP_STATUS_UNAUTHORIZED)
ef416fc2 391 {
392 /*
393 * Flush any error message...
394 */
395
396 httpFlush(http);
397
398 /*
399 * See if we can do authentication...
400 */
401
402 if (cupsDoAuthentication(http, "PUT", resource))
f11a948a 403 {
cb7f98ee 404 status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
ef416fc2 405 break;
f11a948a 406 }
ef416fc2 407
cb7f98ee 408 if (httpReconnect2(http, 30000, NULL))
fa73b229 409 {
cb7f98ee 410 status = HTTP_STATUS_ERROR;
fa73b229 411 break;
412 }
ef416fc2 413
414 continue;
415 }
416#ifdef HAVE_SSL
cb7f98ee 417 else if (status == HTTP_STATUS_UPGRADE_REQUIRED)
ef416fc2 418 {
419 /* Flush any error message... */
420 httpFlush(http);
421
422 /* Reconnect... */
cb7f98ee 423 if (httpReconnect2(http, 30000, NULL))
fa73b229 424 {
cb7f98ee 425 status = HTTP_STATUS_ERROR;
fa73b229 426 break;
427 }
ef416fc2 428
429 /* Upgrade with encryption... */
cb7f98ee 430 httpEncryption(http, HTTP_ENCRYPTION_REQUIRED);
ef416fc2 431
432 /* Try again, this time with encryption enabled... */
433 continue;
434 }
435#endif /* HAVE_SSL */
436 }
cb7f98ee
MS
437 while (status == HTTP_STATUS_UNAUTHORIZED || status == HTTP_STATUS_UPGRADE_REQUIRED ||
438 (status == HTTP_STATUS_ERROR && retries < 2));
ef416fc2 439
440 /*
441 * See if we actually put the file or an error...
442 */
443
cb7f98ee 444 if (status != HTTP_STATUS_CREATED)
355e94dc
MS
445 {
446 _cupsSetHTTPError(status);
ef416fc2 447 httpFlush(http);
355e94dc 448 }
ef416fc2 449
e07d4801
MS
450 DEBUG_printf(("1cupsPutFd: Returning %d...", status));
451
ef416fc2 452 return (status);
453}
454
455
456/*
457 * 'cupsPutFile()' - Put a file on the server.
458 *
5a738aea
MS
459 * This function returns @code HTTP_CREATED@ when the file is stored
460 * successfully.
ef416fc2 461 *
f3c17241 462 * @since CUPS 1.1.20/OS X 10.4@
ef416fc2 463 */
464
ecdc0628 465http_status_t /* O - HTTP status */
568fa3fa 466cupsPutFile(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
ef416fc2 467 const char *resource, /* I - Resource name */
468 const char *filename) /* I - Filename */
469{
470 int fd; /* File descriptor */
471 http_status_t status; /* Status */
472
473
474 /*
475 * Range check input...
476 */
477
478 if (!http || !resource || !filename)
479 {
480 if (http)
481 http->error = EINVAL;
482
cb7f98ee 483 return (HTTP_STATUS_ERROR);
ef416fc2 484 }
485
486 /*
487 * Open the local file...
488 */
489
490 if ((fd = open(filename, O_RDONLY)) < 0)
491 {
492 /*
493 * Couldn't open the file!
494 */
495
496 http->error = errno;
497
cb7f98ee 498 return (HTTP_STATUS_ERROR);
ef416fc2 499 }
500
501 /*
502 * Put the file...
503 */
504
505 status = cupsPutFd(http, resource, fd);
506
507 close(fd);
508
509 return (status);
510}
511
512
513/*
f2d18633 514 * End of "$Id$".
ef416fc2 515 */