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