4 * Get/put file functions for CUPS.
6 * Copyright 2007-2014 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 * Include necessary headers...
22 #include "cups-private.h"
25 #if defined(WIN32) || defined(__EMX__)
29 #endif /* WIN32 || __EMX__ */
33 * 'cupsGetFd()' - Get a file from the server.
35 * This function returns @code HTTP_STATUS_OK@ when the file is successfully retrieved.
37 * @since CUPS 1.1.20/OS X 10.4@
40 http_status_t
/* O - HTTP status */
41 cupsGetFd(http_t
*http
, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
42 const char *resource
, /* I - Resource name */
43 int fd
) /* I - File descriptor */
45 ssize_t bytes
; /* Number of bytes read */
46 char buffer
[8192]; /* Buffer for file */
47 http_status_t status
; /* HTTP status from server */
48 char if_modified_since
[HTTP_MAX_VALUE
];
49 /* If-Modified-Since header */
53 * Range check input...
56 DEBUG_printf(("cupsGetFd(http=%p, resource=\"%s\", fd=%d)", (void *)http
, resource
, fd
));
58 if (!resource
|| fd
< 0)
63 return (HTTP_STATUS_ERROR
);
67 if ((http
= _cupsConnect()) == NULL
)
68 return (HTTP_STATUS_SERVICE_UNAVAILABLE
);
71 * Then send GET requests to the HTTP server...
74 strlcpy(if_modified_since
, httpGetField(http
, HTTP_FIELD_IF_MODIFIED_SINCE
),
75 sizeof(if_modified_since
));
79 if (!_cups_strcasecmp(httpGetField(http
, HTTP_FIELD_CONNECTION
), "close"))
81 httpClearFields(http
);
82 if (httpReconnect2(http
, 30000, NULL
))
84 status
= HTTP_STATUS_ERROR
;
89 httpClearFields(http
);
90 httpSetField(http
, HTTP_FIELD_AUTHORIZATION
, http
->authstring
);
91 httpSetField(http
, HTTP_FIELD_IF_MODIFIED_SINCE
, if_modified_since
);
93 if (httpGet(http
, resource
))
95 if (httpReconnect2(http
, 30000, NULL
))
97 status
= HTTP_STATUS_ERROR
;
102 status
= HTTP_STATUS_UNAUTHORIZED
;
107 while ((status
= httpUpdate(http
)) == HTTP_STATUS_CONTINUE
);
109 if (status
== HTTP_STATUS_UNAUTHORIZED
)
112 * Flush any error message...
118 * See if we can do authentication...
121 if (cupsDoAuthentication(http
, "GET", resource
))
123 status
= HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED
;
127 if (httpReconnect2(http
, 30000, NULL
))
129 status
= HTTP_STATUS_ERROR
;
136 else if (status
== HTTP_STATUS_UPGRADE_REQUIRED
)
138 /* Flush any error message... */
142 if (httpReconnect2(http
, 30000, NULL
))
144 status
= HTTP_STATUS_ERROR
;
148 /* Upgrade with encryption... */
149 httpEncryption(http
, HTTP_ENCRYPTION_REQUIRED
);
151 /* Try again, this time with encryption enabled... */
154 #endif /* HAVE_SSL */
156 while (status
== HTTP_STATUS_UNAUTHORIZED
|| status
== HTTP_STATUS_UPGRADE_REQUIRED
);
159 * See if we actually got the file or an error...
162 if (status
== HTTP_STATUS_OK
)
165 * Yes, copy the file...
168 while ((bytes
= httpRead2(http
, buffer
, sizeof(buffer
))) > 0)
169 write(fd
, buffer
, (size_t)bytes
);
173 _cupsSetHTTPError(status
);
178 * Return the request status...
181 DEBUG_printf(("1cupsGetFd: Returning %d...", status
));
188 * 'cupsGetFile()' - Get a file from the server.
190 * This function returns @code HTTP_STATUS_OK@ when the file is successfully retrieved.
192 * @since CUPS 1.1.20/OS X 10.4@
195 http_status_t
/* O - HTTP status */
196 cupsGetFile(http_t
*http
, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
197 const char *resource
, /* I - Resource name */
198 const char *filename
) /* I - Filename */
200 int fd
; /* File descriptor */
201 http_status_t status
; /* Status */
205 * Range check input...
208 if (!http
|| !resource
|| !filename
)
211 http
->error
= EINVAL
;
213 return (HTTP_STATUS_ERROR
);
220 if ((fd
= open(filename
, O_WRONLY
| O_EXCL
| O_TRUNC
)) < 0)
223 * Couldn't open the file!
228 return (HTTP_STATUS_ERROR
);
235 status
= cupsGetFd(http
, resource
, fd
);
238 * If the file couldn't be gotten, then remove the file...
243 if (status
!= HTTP_STATUS_OK
)
247 * Return the HTTP status code...
255 * 'cupsPutFd()' - Put a file on the server.
257 * This function returns @code HTTP_STATUS_CREATED@ when the file is stored
260 * @since CUPS 1.1.20/OS X 10.4@
263 http_status_t
/* O - HTTP status */
264 cupsPutFd(http_t
*http
, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
265 const char *resource
, /* I - Resource name */
266 int fd
) /* I - File descriptor */
268 ssize_t bytes
; /* Number of bytes read */
269 int retries
; /* Number of retries */
270 char buffer
[8192]; /* Buffer for file */
271 http_status_t status
; /* HTTP status from server */
275 * Range check input...
278 DEBUG_printf(("cupsPutFd(http=%p, resource=\"%s\", fd=%d)", (void *)http
, resource
, fd
));
280 if (!resource
|| fd
< 0)
283 http
->error
= EINVAL
;
285 return (HTTP_STATUS_ERROR
);
289 if ((http
= _cupsConnect()) == NULL
)
290 return (HTTP_STATUS_SERVICE_UNAVAILABLE
);
293 * Then send PUT requests to the HTTP server...
300 if (!_cups_strcasecmp(httpGetField(http
, HTTP_FIELD_CONNECTION
), "close"))
302 httpClearFields(http
);
303 if (httpReconnect2(http
, 30000, NULL
))
305 status
= HTTP_STATUS_ERROR
;
310 DEBUG_printf(("2cupsPutFd: starting attempt, authstring=\"%s\"...",
313 httpClearFields(http
);
314 httpSetField(http
, HTTP_FIELD_AUTHORIZATION
, http
->authstring
);
315 httpSetField(http
, HTTP_FIELD_TRANSFER_ENCODING
, "chunked");
316 httpSetExpect(http
, HTTP_STATUS_CONTINUE
);
318 if (httpPut(http
, resource
))
320 if (httpReconnect2(http
, 30000, NULL
))
322 status
= HTTP_STATUS_ERROR
;
327 status
= HTTP_STATUS_UNAUTHORIZED
;
333 * Wait up to 1 second for a 100-continue response...
336 if (httpWait(http
, 1000))
337 status
= httpUpdate(http
);
339 status
= HTTP_STATUS_CONTINUE
;
341 if (status
== HTTP_STATUS_CONTINUE
)
347 lseek(fd
, 0, SEEK_SET
);
349 while ((bytes
= read(fd
, buffer
, sizeof(buffer
))) > 0)
352 if ((status
= httpUpdate(http
)) != HTTP_STATUS_CONTINUE
)
356 httpWrite2(http
, buffer
, (size_t)bytes
);
359 if (status
== HTTP_STATUS_CONTINUE
)
361 httpWrite2(http
, buffer
, 0);
363 while ((status
= httpUpdate(http
)) == HTTP_STATUS_CONTINUE
);
366 if (status
== HTTP_STATUS_ERROR
&& !retries
)
368 DEBUG_printf(("2cupsPutFd: retry on status %d", status
));
372 /* Flush any error message... */
376 if (httpReconnect2(http
, 30000, NULL
))
378 status
= HTTP_STATUS_ERROR
;
386 DEBUG_printf(("2cupsPutFd: status=%d", status
));
388 if (status
== HTTP_STATUS_UNAUTHORIZED
)
391 * Flush any error message...
397 * See if we can do authentication...
400 if (cupsDoAuthentication(http
, "PUT", resource
))
402 status
= HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED
;
406 if (httpReconnect2(http
, 30000, NULL
))
408 status
= HTTP_STATUS_ERROR
;
415 else if (status
== HTTP_STATUS_UPGRADE_REQUIRED
)
417 /* Flush any error message... */
421 if (httpReconnect2(http
, 30000, NULL
))
423 status
= HTTP_STATUS_ERROR
;
427 /* Upgrade with encryption... */
428 httpEncryption(http
, HTTP_ENCRYPTION_REQUIRED
);
430 /* Try again, this time with encryption enabled... */
433 #endif /* HAVE_SSL */
435 while (status
== HTTP_STATUS_UNAUTHORIZED
|| status
== HTTP_STATUS_UPGRADE_REQUIRED
||
436 (status
== HTTP_STATUS_ERROR
&& retries
< 2));
439 * See if we actually put the file or an error...
442 if (status
!= HTTP_STATUS_CREATED
)
444 _cupsSetHTTPError(status
);
448 DEBUG_printf(("1cupsPutFd: Returning %d...", status
));
455 * 'cupsPutFile()' - Put a file on the server.
457 * This function returns @code HTTP_CREATED@ when the file is stored
460 * @since CUPS 1.1.20/OS X 10.4@
463 http_status_t
/* O - HTTP status */
464 cupsPutFile(http_t
*http
, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
465 const char *resource
, /* I - Resource name */
466 const char *filename
) /* I - Filename */
468 int fd
; /* File descriptor */
469 http_status_t status
; /* Status */
473 * Range check input...
476 if (!http
|| !resource
|| !filename
)
479 http
->error
= EINVAL
;
481 return (HTTP_STATUS_ERROR
);
485 * Open the local file...
488 if ((fd
= open(filename
, O_RDONLY
)) < 0)
491 * Couldn't open the file!
496 return (HTTP_STATUS_ERROR
);
503 status
= cupsPutFd(http
, resource
, fd
);