2 * "$Id: getputfile.c 11173 2013-07-23 12:31:34Z msweet $"
4 * Get/put file functions for CUPS.
6 * Copyright 2007-2012 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products.
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/".
15 * This file is subject to the Apple OS-Developed Software exception.
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.
26 * Include necessary headers...
29 #include "cups-private.h"
32 #if defined(WIN32) || defined(__EMX__)
36 #endif /* WIN32 || __EMX__ */
40 * 'cupsGetFd()' - Get a file from the server.
42 * This function returns @code HTTP_OK@ when the file is successfully retrieved.
44 * @since CUPS 1.1.20/OS X 10.4@
47 http_status_t /* O - HTTP status */
48 cupsGetFd(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
49 const char *resource, /* I - Resource name */
50 int fd) /* I - File descriptor */
52 int bytes; /* Number of bytes read */
53 char buffer[8192]; /* Buffer for file */
54 http_status_t status; /* HTTP status from server */
55 char if_modified_since[HTTP_MAX_VALUE];
56 /* If-Modified-Since header */
60 * Range check input...
63 DEBUG_printf(("cupsGetFd(http=%p, resource=\"%s\", fd=%d)", http,
66 if (!resource || fd < 0)
75 if ((http = _cupsConnect()) == NULL)
76 return (HTTP_SERVICE_UNAVAILABLE);
79 * Then send GET requests to the HTTP server...
82 strlcpy(if_modified_since, httpGetField(http, HTTP_FIELD_IF_MODIFIED_SINCE),
83 sizeof(if_modified_since));
87 httpClearFields(http);
88 httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
89 httpSetField(http, HTTP_FIELD_IF_MODIFIED_SINCE, if_modified_since);
91 if (httpGet(http, resource))
93 if (httpReconnect(http))
100 status = HTTP_UNAUTHORIZED;
105 while ((status = httpUpdate(http)) == HTTP_CONTINUE);
107 if (status == HTTP_UNAUTHORIZED)
110 * Flush any error message...
116 * See if we can do authentication...
119 if (cupsDoAuthentication(http, "GET", resource))
121 status = HTTP_AUTHORIZATION_CANCELED;
125 if (httpReconnect(http))
134 else if (status == HTTP_UPGRADE_REQUIRED)
136 /* Flush any error message... */
140 if (httpReconnect(http))
146 /* Upgrade with encryption... */
147 httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
149 /* Try again, this time with encryption enabled... */
152 #endif /* HAVE_SSL */
154 while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED);
157 * See if we actually got the file or an error...
160 if (status == HTTP_OK)
163 * Yes, copy the file...
166 while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0)
167 write(fd, buffer, bytes);
171 _cupsSetHTTPError(status);
176 * Return the request status...
179 DEBUG_printf(("1cupsGetFd: Returning %d...", status));
186 * 'cupsGetFile()' - Get a file from the server.
188 * This function returns @code HTTP_OK@ when the file is successfully retrieved.
190 * @since CUPS 1.1.20/OS X 10.4@
193 http_status_t /* O - HTTP status */
194 cupsGetFile(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
195 const char *resource, /* I - Resource name */
196 const char *filename) /* I - Filename */
198 int fd; /* File descriptor */
199 http_status_t status; /* Status */
203 * Range check input...
206 if (!http || !resource || !filename)
209 http->error = EINVAL;
218 if ((fd = open(filename, O_WRONLY | O_EXCL | O_TRUNC)) < 0)
221 * Couldn't open the file!
233 status = cupsGetFd(http, resource, fd);
236 * If the file couldn't be gotten, then remove the file...
241 if (status != HTTP_OK)
245 * Return the HTTP status code...
253 * 'cupsPutFd()' - Put a file on the server.
255 * This function returns @code HTTP_CREATED@ when the file is stored
258 * @since CUPS 1.1.20/OS X 10.4@
261 http_status_t /* O - HTTP status */
262 cupsPutFd(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
263 const char *resource, /* I - Resource name */
264 int fd) /* I - File descriptor */
266 int bytes, /* Number of bytes read */
267 retries; /* Number of retries */
268 char buffer[8192]; /* Buffer for file */
269 http_status_t status; /* HTTP status from server */
273 * Range check input...
276 DEBUG_printf(("cupsPutFd(http=%p, resource=\"%s\", fd=%d)", http,
279 if (!resource || fd < 0)
282 http->error = EINVAL;
288 if ((http = _cupsConnect()) == NULL)
289 return (HTTP_SERVICE_UNAVAILABLE);
292 * Then send PUT requests to the HTTP server...
299 DEBUG_printf(("2cupsPutFd: starting attempt, authstring=\"%s\"...",
302 httpClearFields(http);
303 httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
304 httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, "chunked");
305 httpSetExpect(http, HTTP_CONTINUE);
307 if (httpPut(http, resource))
309 if (httpReconnect(http))
316 status = HTTP_UNAUTHORIZED;
322 * Wait up to 1 second for a 100-continue response...
325 if (httpWait(http, 1000))
326 status = httpUpdate(http);
328 status = HTTP_CONTINUE;
330 if (status == HTTP_CONTINUE)
336 lseek(fd, 0, SEEK_SET);
338 while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
341 if ((status = httpUpdate(http)) != HTTP_CONTINUE)
345 httpWrite2(http, buffer, bytes);
348 if (status == HTTP_CONTINUE)
350 httpWrite2(http, buffer, 0);
352 while ((status = httpUpdate(http)) == HTTP_CONTINUE);
355 if (status == HTTP_ERROR && !retries)
357 DEBUG_printf(("2cupsPutFd: retry on status %d", status));
361 /* Flush any error message... */
365 if (httpReconnect(http))
375 DEBUG_printf(("2cupsPutFd: status=%d", status));
377 if (status == HTTP_UNAUTHORIZED)
380 * Flush any error message...
386 * See if we can do authentication...
389 if (cupsDoAuthentication(http, "PUT", resource))
391 status = HTTP_AUTHORIZATION_CANCELED;
395 if (httpReconnect(http))
404 else if (status == HTTP_UPGRADE_REQUIRED)
406 /* Flush any error message... */
410 if (httpReconnect(http))
416 /* Upgrade with encryption... */
417 httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
419 /* Try again, this time with encryption enabled... */
422 #endif /* HAVE_SSL */
424 while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED ||
425 (status == HTTP_ERROR && retries < 2));
428 * See if we actually put the file or an error...
431 if (status != HTTP_CREATED)
433 _cupsSetHTTPError(status);
437 DEBUG_printf(("1cupsPutFd: Returning %d...", status));
444 * 'cupsPutFile()' - Put a file on the server.
446 * This function returns @code HTTP_CREATED@ when the file is stored
449 * @since CUPS 1.1.20/OS X 10.4@
452 http_status_t /* O - HTTP status */
453 cupsPutFile(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
454 const char *resource, /* I - Resource name */
455 const char *filename) /* I - Filename */
457 int fd; /* File descriptor */
458 http_status_t status; /* Status */
462 * Range check input...
465 if (!http || !resource || !filename)
468 http->error = EINVAL;
474 * Open the local file...
477 if ((fd = open(filename, O_RDONLY)) < 0)
480 * Couldn't open the file!
492 status = cupsPutFd(http, resource, fd);
501 * End of "$Id: getputfile.c 11173 2013-07-23 12:31:34Z msweet $".