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